1.1 --- a/templates/ops.c Mon Jan 30 22:32:38 2017 +0100
1.2 +++ b/templates/ops.c Mon Jan 30 22:34:46 2017 +0100
1.3 @@ -1,6 +1,6 @@
1.4 /* Common operations.
1.5
1.6 -Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
1.7 +Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
1.8
1.9 This program is free software; you can redistribute it and/or modify it under
1.10 the terms of the GNU General Public License as published by the Free Software
1.11 @@ -21,6 +21,7 @@
1.12 #include "progops.h" /* for raising errors */
1.13 #include "progconsts.h"
1.14 #include "progtypes.h"
1.15 +#include <stdio.h>
1.16
1.17 /* Direct access and manipulation of static objects. */
1.18
1.19 @@ -202,7 +203,7 @@
1.20 if (__is_instance(context))
1.21 {
1.22 if (__test_common_instance(context, __TYPEPOS(attr.context), __TYPECODE(attr.context)))
1.23 - return __replace_context(context, attr);
1.24 + return __update_context(context, attr);
1.25 else
1.26 __raise_type_error();
1.27 }
1.28 @@ -210,34 +211,58 @@
1.29 /* Test for access to a type class attribute using a type instance. */
1.30
1.31 if (__test_specific_type(attr.context, &__TYPE_CLASS_TYPE) && __is_type_instance(context))
1.32 - return __replace_context(context, attr);
1.33 + return __update_context(context, attr);
1.34
1.35 /* Otherwise, preserve the attribute as retrieved. */
1.36
1.37 return attr;
1.38 }
1.39
1.40 -__attr __replace_context(__ref context, __attr attr)
1.41 -{
1.42 - __attr out;
1.43 -
1.44 - /* Set the context. */
1.45 -
1.46 - out.context = context;
1.47 -
1.48 - /* Reference a callable version of the attribute by obtaining the bound
1.49 - method reference from the __fn__ special attribute. */
1.50 -
1.51 - out.value = __load_via_object(attr.value, __ATTRPOS(__fn__)).b;
1.52 - return out;
1.53 -}
1.54 -
1.55 __attr __update_context(__ref context, __attr attr)
1.56 {
1.57 __attr out = {.context=context, .value=attr.value};
1.58 return out;
1.59 }
1.60
1.61 +/* Context testing for invocations. */
1.62 +
1.63 +int __type_method_invocation(__attr attr)
1.64 +{
1.65 + __attr parent;
1.66 +
1.67 + /* Require instances, not classes, where methods are function instances. */
1.68 +
1.69 + if (!__is_instance(attr.value))
1.70 + return 0;
1.71 +
1.72 + /* Access the parent of the callable and test if it is the type object. */
1.73 +
1.74 + parent = __check_and_load_via_object_null(attr.value, __ATTRPOS(__parent__), __ATTRCODE(__parent__));
1.75 + return ((parent.value != 0) && __test_specific_type(parent.value, &__TYPE_CLASS_TYPE) && __is_type_instance(attr.context));
1.76 +}
1.77 +
1.78 +__attr (*__get_function(__attr attr))(__attr[])
1.79 +{
1.80 + /* Require null or instance contexts for functions and methods respectively,
1.81 + or type instance contexts for type methods. */
1.82 +
1.83 + if ((attr.context == 0) || __is_instance(attr.context) || __type_method_invocation(attr))
1.84 + return __load_via_object(attr.value, __ATTRPOS(__fn__)).fn;
1.85 + else
1.86 + return __load_via_object(attr.value, __ATTRPOS(__fn__)).inv;
1.87 +}
1.88 +
1.89 +__attr (*__check_and_get_function(__attr attr))(__attr[])
1.90 +{
1.91 + /* Require null or instance contexts for functions and methods respectively,
1.92 + or type instance contexts for type methods. */
1.93 +
1.94 + if ((attr.context == 0) || __is_instance(attr.context) || __type_method_invocation(attr))
1.95 + return __check_and_load_via_object(attr.value, __ATTRPOS(__fn__), __ATTRCODE(__fn__)).fn;
1.96 + else
1.97 + return __check_and_load_via_object(attr.value, __ATTRPOS(__fn__), __ATTRCODE(__fn__)).inv;
1.98 +}
1.99 +
1.100 /* Basic structure tests. */
1.101
1.102 int __WITHIN(__ref obj, int pos)