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/