Lichen

Changeset

855:638e28765ea5
2018-07-12 Paul Boddie raw files shortlog changelog graph Merged changes from the default branch. trailing-data
templates/ops.c (file) templates/progops.c (file) templates/progops.h (file)
     1.1 --- a/deducer.py	Thu Jul 12 00:15:16 2018 +0200
     1.2 +++ b/deducer.py	Thu Jul 12 18:53:58 2018 +0200
     1.3 @@ -2938,7 +2938,13 @@
     1.4              # Produce an advisory instruction regarding the context.
     1.5  
     1.6              if context_var:
     1.7 -                if context_test in ("ignore", "replace"):
     1.8 +
     1.9 +                # Only verify the context for invocation purposes if a suitable
    1.10 +                # test has been performed.
    1.11 +
    1.12 +                if context_test in ("ignore", "replace") or \
    1.13 +                   final_method in ("access-invoke", "static-invoke"):
    1.14 +
    1.15                      emit(("<context_identity_verified>", context_var))
    1.16                  else:
    1.17                      emit(("<context_identity>", context_var))
     2.1 --- a/templates/ops.c	Thu Jul 12 00:15:16 2018 +0200
     2.2 +++ b/templates/ops.c	Thu Jul 12 18:53:58 2018 +0200
     2.3 @@ -231,7 +231,7 @@
     2.4  
     2.5  /* Context-related operations. */
     2.6  
     2.7 -int __test_context_update(__attr context, __attr attr)
     2.8 +int __test_context_update(__attr context, __attr attr, int invoke)
     2.9  {
    2.10      /* Return whether the context should be updated for the attribute. */
    2.11  
    2.12 @@ -258,6 +258,11 @@
    2.13              __raise_type_error();
    2.14      }
    2.15  
    2.16 +    /* Without a null or instance context, an invocation cannot be performed. */
    2.17 +
    2.18 +    if (invoke)
    2.19 +        __raise_unbound_method_error();
    2.20 +
    2.21      /* Test for access to a type class attribute using a type instance. */
    2.22  
    2.23      if (__test_specific_type(attrcontextvalue, &__TYPE_CLASS_TYPE) && __is_type_instance(__VALUE(context)))
    2.24 @@ -272,7 +277,7 @@
    2.25  {
    2.26      /* Update the context or return the unchanged attribute. */
    2.27  
    2.28 -    if (__test_context_update(context, attr))
    2.29 +    if (__test_context_update(context, attr, 0))
    2.30          return __update_context(context, attr);
    2.31      else
    2.32          return attr;
    2.33 @@ -288,7 +293,7 @@
    2.34      /* Revert the local context to that employed by the attribute if the
    2.35         supplied context is not appropriate. */
    2.36  
    2.37 -    if (!__test_context_update(context, attr))
    2.38 +    if (!__test_context_update(context, attr, 1))
    2.39          contexts[target] = __CONTEXT_AS_VALUE(attr);
    2.40      return attr;
    2.41  }
    2.42 @@ -297,7 +302,7 @@
    2.43  {
    2.44      /* Set the local context to the specified context if appropriate. */
    2.45  
    2.46 -    if (__test_context_update(context, __ATTRVALUE(value)))
    2.47 +    if (__test_context_update(context, __ATTRVALUE(value), 1))
    2.48          contexts[target] = context;
    2.49      return __ATTRVALUE(value);
    2.50  }
     3.1 --- a/templates/ops.h	Thu Jul 12 00:15:16 2018 +0200
     3.2 +++ b/templates/ops.h	Thu Jul 12 18:53:58 2018 +0200
     3.3 @@ -101,7 +101,7 @@
     3.4  
     3.5  /* Context-related operations. */
     3.6  
     3.7 -int __test_context_update(__attr context, __attr attr);
     3.8 +int __test_context_update(__attr context, __attr attr, int invoke);
     3.9  __attr __test_context(__attr context, __attr attr);
    3.10  __attr __update_context(__attr context, __attr attr);
    3.11  __attr __test_context_revert(int target, __attr context, __attr attr, __attr contexts[]);
     4.1 --- a/templates/progops.c	Thu Jul 12 00:15:16 2018 +0200
     4.2 +++ b/templates/progops.c	Thu Jul 12 18:53:58 2018 +0200
     4.3 @@ -151,6 +151,11 @@
     4.4      __Raise(__new___builtins___core_OverflowError(__NULL));
     4.5  }
     4.6  
     4.7 +void __raise_unbound_method_error()
     4.8 +{
     4.9 +    __Raise(__new___builtins___core_UnboundMethodInvocation(__NULL));
    4.10 +}
    4.11 +
    4.12  void __raise_type_error()
    4.13  {
    4.14      __Raise(__new___builtins___core_TypeError(__NULL));
     5.1 --- a/templates/progops.h	Thu Jul 12 00:15:16 2018 +0200
     5.2 +++ b/templates/progops.h	Thu Jul 12 18:53:58 2018 +0200
     5.3 @@ -52,6 +52,7 @@
     5.4  void __raise_memory_error();
     5.5  void __raise_os_error(__attr value, __attr arg);
     5.6  void __raise_overflow_error();
     5.7 +void __raise_unbound_method_error();
     5.8  void __raise_underflow_error();
     5.9  void __raise_zero_division_error();
    5.10  void __raise_type_error();
     6.1 --- a/tests/methods_rebound.py	Thu Jul 12 00:15:16 2018 +0200
     6.2 +++ b/tests/methods_rebound.py	Thu Jul 12 18:53:58 2018 +0200
     6.3 @@ -13,9 +13,32 @@
     6.4  
     6.5  d = D()
     6.6  
     6.7 +def fn():
     6.8 +    return 456
     6.9 +
    6.10 +class E:
    6.11 +    f = fn
    6.12 +    g = C.f
    6.13 +
    6.14 +e = E()
    6.15 +
    6.16  print c.f.__name__                  # f
    6.17  print c.f()                         # <__main__.C instance>
    6.18                                      # 123
    6.19  print d.f.__name__                  # wrapper
    6.20  print d.f()                         # <__main__.C instance>
    6.21                                      # 123
    6.22 +
    6.23 +print e.f.__name__                  # fn
    6.24 +print e.f()                         # 456
    6.25 +print e.g.__name__                  # f
    6.26 +
    6.27 +try:
    6.28 +    print e.g()
    6.29 +except TypeError:
    6.30 +    print "e.g(): e is an incompatible instance for E.g which is C.f"
    6.31 +
    6.32 +g = get_using(E.g, c)
    6.33 +print g.__name__                    # f
    6.34 +print g()                           # <__main__.C instance>
    6.35 +                                    # 123
     7.1 --- a/translator.py	Thu Jul 12 00:15:16 2018 +0200
     7.2 +++ b/translator.py	Thu Jul 12 18:53:58 2018 +0200
     7.3 @@ -1070,9 +1070,21 @@
     7.4  
     7.5          context_required = True
     7.6          have_access_context = isinstance(expr, AttrResult)
     7.7 +
     7.8 +        # The context identity is merely the thing providing the context.
     7.9 +        # A verified context is one that does not need further testing for
    7.10 +        # suitability.
    7.11 +
    7.12          context_identity = have_access_context and expr.context()
    7.13          context_verified = have_access_context and expr.context_verified()
    7.14 +
    7.15 +        # The presence of any test operations in the accessor expression.
    7.16 +        # With such operations present, the expression cannot be eliminated.
    7.17 +
    7.18          tests_accessor = have_access_context and expr.tests_accessor()
    7.19 +
    7.20 +        # Parameter details and parameter list dimensions.
    7.21 +
    7.22          parameters = None
    7.23          num_parameters = None
    7.24          num_defaults = None
    7.25 @@ -1252,11 +1264,13 @@
    7.26  
    7.27          if context_required:
    7.28              if have_access_context:
    7.29 -                args = [context_identity]
    7.30 +                context_arg = context_identity
    7.31              else:
    7.32 -                args = ["__CONTEXT_AS_VALUE(%s)" % target_var]
    7.33 +                context_arg = "__CONTEXT_AS_VALUE(%s)" % target_var
    7.34          else:
    7.35 -            args = ["__NULL"]
    7.36 +            context_arg = "__NULL"
    7.37 +
    7.38 +        args = [context_arg]
    7.39  
    7.40          # Complete the array with null values, permitting tests for a complete
    7.41          # set of arguments.
    7.42 @@ -1398,25 +1412,23 @@
    7.43          elif function:
    7.44              if context_required:
    7.45  
    7.46 -                # With context_verified or context_identity...
    7.47 -
    7.48 -                if have_access_context:
    7.49 +                # Avoid further context testing if appropriate.
    7.50 +
    7.51 +                if have_access_context and context_verified:
    7.52                      emit("__get_function_member(%s)" % target_expr)
    7.53  
    7.54                  # Otherwise, test the context for the function/method.
    7.55  
    7.56                  else:
    7.57 -                    emit("__get_function(__CONTEXT_AS_VALUE(%s), %s)" % (
    7.58 -                        target_var, target_expr))
    7.59 +                    emit("__get_function(%s, %s)" % (context_arg, target_expr))
    7.60              else:
    7.61                  emit("_get_function_member(%s)" % target_expr)
    7.62  
    7.63          # With known parameters, the target can be tested.
    7.64  
    7.65          elif known_parameters:
    7.66 -            context_arg = context_required and args[0] or "__NULL"
    7.67              if self.always_callable(refs):
    7.68 -                if context_verified or context_identity:
    7.69 +                if context_verified:
    7.70                      emit("__get_function_member(%s)" % target_expr)
    7.71                  else:
    7.72                      emit("__get_function(%s, %s)" % (context_arg, target_expr))