Second version of the POC implementation in response to feedback.

On Fri, Oct 29, 2021 at 7:17 PM Chris Angelico <ros...@gmail.com> wrote:
>
> https://github.com/Rosuav/cpython/tree/pep-671
>
> So uhh... anyone who knows about the internals of CPython and wants to
> join me on this, I would *really* appreciate coauthors!

Still interested in coauthors who know CPython internals. That hasn't changed.

> The implementation ended up a lot more invasive than I originally
> planned. Some of that is inherent to the problem, but other parts
> might be able to be done more cleanly. The way I've done it:

It's still more invasive than intended :)

> * Argument defaults (either in __defaults__ or __kwdefaults__) are now
> tuples of (desc, value) or (desc,) for early-bound and late-bound
> respectively

This is the part that's changed. Instead of tuples in those slots,
there are now pairs of slots __defaults__ with __defaults_extra__, and
__kwdefaults__ with __kwdefaults_extra__. For every late-bound
default, there will be Ellipsis as a placeholder value, and then a
disambiguating marker in the extras tuple/dict; None means that it's
actually the value Ellipsis after all, or a string indicates that it's
a late-bound default.

> * Early-bound defaults get mapped as normal. Late-bound defaults are
> left unbound at time of function call.
> * For each late-bound default as of the 'def' statement, a check is
> coded: if the local is unbound, set it based on the given expression.

This part of the implementation is still the same.

> This means that it's possible to replace an early-bound default with a
> late-bound, but instead of actually evaluating the expression, it just
> leaves it unbound:
>
> >>> def f(x=1): print(x)
> ...
> >>> f.__defaults__
> ((None, 1),)
> >>> f.__defaults__ = ((None,),)
> >>> f()
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<stdin>", line 1, in f
> UnboundLocalError: cannot access local variable 'x' where it is not
> associated with a value
> >>>

These shenanigans can still be done, but instead of changing
__defaults__, it would be done by changing __defaults_extra__:

>>> def f(x=1): print(x)
...
>>> f.__defaults__
(1,)
>>> f.__defaults_extra__ = ('',)
>>> f.__defaults__ = (...,)
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in f
UnboundLocalError: cannot access local variable 'x' where it is not
associated with a value
>>>

> So far unimplemented is the description of the argument default. My
> plan is for early-bound defaults to have None there (as they currently
> do), but late-bound ones get the source code. (In theory, it may be of
> value to retain the source code for earlies too, which would allow hex
> or octal integer literals to show up in help() as such, rather than
> showing the (decimal) repr of the resulting value.) Anyone got good
> pointers on how to do this, or is that likely to be impractical?

Much the same here. Anyone know of a good way to get source code
sections during compilation? If not, I'll dig around when I get a
moment.

One difference is that early-bound defaults probably won't get
descriptions, although it's certainly possible.

> Feel free to criticize my code. As you'll see from the commit messages
> in that branch, I have no idea what I'm doing here :)
>

Believe you me, this part hasn't changed a bit.... :)

So there's really only been one notable change to the implementation.
Hopefully this should ensure backward compatibility. There are a few
failing tests and I'm going through them now.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/TNSOFPA4V3Y7F3W43MNEEXZ43YWGASJS/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to