1.1 --- a/deducer.py Sat Sep 02 22:08:53 2023 +0200
1.2 +++ b/deducer.py Sun Sep 03 00:24:29 2023 +0200
1.3 @@ -2907,6 +2907,12 @@
1.4 elif final_method in ("static", "static-invoke"):
1.5 accessor = ("__load_static_ignore", origin)
1.6
1.7 + # Define any replacement context variable plus the default eventual
1.8 + # context variable.
1.9 +
1.10 + replacement_context_var = "<new_context>"
1.11 + final_context_var = context_var
1.12 +
1.13 # Wrap accesses in context operations.
1.14
1.15 if context_test == "test":
1.16 @@ -2914,7 +2920,8 @@
1.17 # Test and combine the context with static attribute details.
1.18
1.19 if final_method == "static":
1.20 - emit(("__load_static_test", context_var, origin))
1.21 + emit(("__load_static_test", replacement_context_var, context_var, origin))
1.22 + final_context_var = replacement_context_var
1.23
1.24 # Test the context, storing it separately if required for the
1.25 # immediately invoked static attribute.
1.26 @@ -2932,14 +2939,16 @@
1.27 # appropriate.
1.28
1.29 else:
1.30 - emit(("__test_context", context_var, accessor))
1.31 + emit(("__test_context", replacement_context_var, context_var, accessor))
1.32 + final_context_var = replacement_context_var
1.33
1.34 elif context_test == "replace":
1.35
1.36 # Produce an object with updated context.
1.37
1.38 if final_method == "static":
1.39 - emit(("__load_static_replace", context_var, origin))
1.40 + emit(("__load_static_replace", replacement_context_var, context_var, origin))
1.41 + final_context_var = replacement_context_var
1.42
1.43 # Omit the context update operation where the target is static
1.44 # and the context is recorded separately.
1.45 @@ -2956,7 +2965,8 @@
1.46 # Update the context in the attribute details.
1.47
1.48 else:
1.49 - emit(("__update_context", context_var, accessor))
1.50 + emit(("__update_context", replacement_context_var, context_var, accessor))
1.51 + final_context_var = replacement_context_var
1.52
1.53 # Omit the accessor for assignments and for invocations of static
1.54 # targets. Otherwise, emit the accessor which may involve the
1.55 @@ -2967,7 +2977,7 @@
1.56
1.57 # Produce an advisory instruction regarding the context.
1.58
1.59 - if context_var:
1.60 + if final_context_var:
1.61
1.62 # Only verify the context for invocation purposes if a suitable
1.63 # test has been performed.
1.64 @@ -2975,9 +2985,9 @@
1.65 if context_test in ("ignore", "replace") or \
1.66 final_method in ("access-invoke", "static-invoke"):
1.67
1.68 - emit(("<context_identity_verified>", context_var))
1.69 + emit(("<context_identity_verified>", final_context_var))
1.70 else:
1.71 - emit(("<context_identity>", context_var))
1.72 + emit(("<context_identity>", final_context_var))
1.73
1.74 # Produce an advisory instruction regarding the final attribute.
1.75
2.1 --- a/encoders.py Sat Sep 02 22:08:53 2023 +0200
2.2 +++ b/encoders.py Sun Sep 03 00:24:29 2023 +0200
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Encoder functions, producing representations of program objects.
2.6
2.7 -Copyright (C) 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2016, 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
3.1 --- a/templates/native/introspection.c Sat Sep 02 22:08:53 2023 +0200
3.2 +++ b/templates/native/introspection.c Sun Sep 03 00:24:29 2023 +0200
3.3 @@ -48,7 +48,7 @@
3.4
3.5 /* Update the context to the object if it is a method. */
3.6
3.7 - return __update_context(obj, out);
3.8 + return __update_context(__result, obj, out);
3.9 }
3.10
3.11 return out;
4.1 --- a/templates/native/program.c Sat Sep 02 22:08:53 2023 +0200
4.2 +++ b/templates/native/program.c Sun Sep 03 00:24:29 2023 +0200
4.3 @@ -28,7 +28,7 @@
4.4
4.5 __attr __fn_native_program_get_using(__attr __result, __attr __self, __attr callable, __attr instance)
4.6 {
4.7 - return __test_context(instance, callable);
4.8 + return __test_context(__result, instance, callable);
4.9 }
4.10
4.11 /* Module initialisation. */
5.1 --- a/templates/ops.c Sat Sep 02 22:08:53 2023 +0200
5.2 +++ b/templates/ops.c Sun Sep 03 00:24:29 2023 +0200
5.3 @@ -47,14 +47,14 @@
5.4 return __ATTRVALUE(obj);
5.5 }
5.6
5.7 -__attr __load_static_replace(__attr context, __ref obj)
5.8 +__attr __load_static_replace(__attr __context, __attr context, __ref obj)
5.9 {
5.10 - return __update_context(context, __ATTRVALUE(obj));
5.11 + return __update_context(__context, context, __ATTRVALUE(obj));
5.12 }
5.13
5.14 -__attr __load_static_test(__attr context, __ref obj)
5.15 +__attr __load_static_test(__attr __context, __attr context, __ref obj)
5.16 {
5.17 - return __test_context(context, __ATTRVALUE(obj));
5.18 + return __test_context(__context, context, __ATTRVALUE(obj));
5.19 }
5.20
5.21 /* Direct retrieval operations, returning attribute locations. */
5.22 @@ -249,18 +249,34 @@
5.23 return 0;
5.24 }
5.25
5.26 -__attr __test_context(__attr context, __attr attr)
5.27 +__attr __test_context(__attr __context, __attr context, __attr attr)
5.28 {
5.29 /* Update the context or return the unchanged attribute. */
5.30
5.31 if (__test_context_update(context, attr, 0))
5.32 - return __update_context(context, attr);
5.33 + return __update_context(__context, context, attr);
5.34 else
5.35 return attr;
5.36 }
5.37
5.38 -__attr __update_context(__attr context, __attr attr)
5.39 +__attr __update_context(__attr __context, __attr context, __attr attr)
5.40 {
5.41 + /* Support context replacement in a similar fashion to value replacement in
5.42 + floats. */
5.43 +
5.44 + __ref obj = __VALUE(__context);
5.45 +
5.46 + /* With any existing wrapper object allocated, replace the attributes and
5.47 + return the same context. */
5.48 +
5.49 + if ((obj != NULL) && __is_instance(obj) &&
5.50 + (__get_class(obj) == &__builtins___core_wrapper))
5.51 + {
5.52 + __store_via_attr_ref(__get_object_attr_ref(obj, __context__), context);
5.53 + __store_via_attr_ref(__get_object_attr_ref(obj, __value__), attr);
5.54 + return __context;
5.55 + }
5.56 +
5.57 return __new_wrapper(context, attr);
5.58 }
5.59
5.60 @@ -426,7 +442,9 @@
5.61
5.62 /* Store an attribute in a target location. For targets that support value
5.63 replacement, a copied object is assigned when initialising the target.
5.64 - NOTE: Only floats are currently supported for value replacement. */
5.65 +
5.66 + NOTE: Only floats and wrappers are currently supported for value replacement.
5.67 + A special copy attribute could be employed to make this generic. */
5.68
5.69 __attr __set_attr(volatile __attr *target, __attr attr)
5.70 {
5.71 @@ -442,8 +460,13 @@
5.72 /* Value is replaceable and should be copied to avoid inadvertent
5.73 sharing. */
5.74
5.75 - if ((obj != NULL) && __is_instance(obj) && (__get_class(obj) == &__builtins___float_float))
5.76 - attr = __ATTRVALUE(__COPY(obj, sizeof(__obj___builtins___float_float)));
5.77 + if ((obj != NULL) && __is_instance(obj))
5.78 + {
5.79 + if (__get_class(obj) == &__builtins___float_float)
5.80 + attr = __ATTRVALUE(__COPY(obj, __INSTANCESIZE(__builtins___float_float)));
5.81 + else if (__get_class(obj) == &__builtins___core_wrapper)
5.82 + attr = __ATTRVALUE(__COPY(obj, __INSTANCESIZE(__builtins___core_wrapper)));
5.83 + }
5.84
5.85 /* Set and return the attribute. */
5.86
6.1 --- a/templates/ops.h Sat Sep 02 22:08:53 2023 +0200
6.2 +++ b/templates/ops.h Sun Sep 03 00:24:29 2023 +0200
6.3 @@ -29,8 +29,8 @@
6.4 /* Direct access and manipulation of static objects. */
6.5
6.6 __attr __load_static_ignore(__ref obj);
6.7 -__attr __load_static_replace(__attr context, __ref obj);
6.8 -__attr __load_static_test(__attr context, __ref obj);
6.9 +__attr __load_static_replace(__attr __context, __attr context, __ref obj);
6.10 +__attr __load_static_test(__attr __context, __attr context, __ref obj);
6.11
6.12 /* Direct retrieval operations, returning attribute locations. */
6.13
6.14 @@ -105,11 +105,12 @@
6.15 /* Context-related operations. */
6.16
6.17 int __test_context_update(__attr context, __attr attr, int invoke);
6.18 -__attr __test_context(__attr context, __attr attr);
6.19 -__attr __update_context(__attr context, __attr attr);
6.20 __attr __test_context_revert(int target, __attr context, __attr attr, __attr contexts[]);
6.21 __attr __test_context_static(int target, __attr context, __ref value, __attr contexts[]);
6.22
6.23 +__attr __test_context(__attr __context, __attr context, __attr attr);
6.24 +__attr __update_context(__attr __context, __attr context, __attr attr);
6.25 +
6.26 #define __get_accessor(__TARGET) (__tmp_values[__TARGET])
6.27 #define __get_attr_ref(__TARGET) (__tmp_attr_refs[__TARGET])
6.28 #define __get_context(__TARGET) (__tmp_contexts[__TARGET])
7.1 --- a/translator.py Sat Sep 02 22:08:53 2023 +0200
7.2 +++ b/translator.py Sun Sep 03 00:24:29 2023 +0200
7.3 @@ -554,6 +554,7 @@
7.4 "<expr>" : attr_expr,
7.5 "<name>" : attr_expr,
7.6 "<assexpr>" : self.in_assignment,
7.7 + "<new_context>" : self.result_target_name or "__NULL",
7.8 }
7.9
7.10 subs.update(self.temp_subs)
7.11 @@ -603,12 +604,12 @@
7.12 instruction = ("__to_error", instruction)
7.13 accessor_test = True
7.14
7.15 - # Intercept accessor storage.
7.16 + # Detect accessor storage.
7.17
7.18 elif instruction[0] == "<set_accessor>":
7.19 accessor_stored = True
7.20
7.21 - # Intercept attribute reference storage.
7.22 + # Detect attribute reference storage.
7.23
7.24 elif instruction[0] == "<set_attr_ref>":
7.25 attribute_ref_stored = True