[pypy-commit] pypy py3k-kwonly-builtin: A much simpler solution gets us most of the way there (thanks fijal):
arigo
pypy.commits at gmail.com
Sat Aug 20 03:18:25 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3k-kwonly-builtin
Changeset: r86336:d428c0d4802a
Date: 2016-08-20 09:15 +0200
http://bitbucket.org/pypy/pypy/changeset/d428c0d4802a/
Log: A much simpler solution gets us most of the way there (thanks
fijal): rely on the mapdict logic
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -38,7 +38,9 @@
'name?',
'w_kw_defs?']
- def __init__(self, space, code, w_globals=None, defs_w=[], w_kw_defs=None,
+ w_kw_defs = None
+
+ def __init__(self, space, code, w_globals=None, defs_w=[], kw_defs_w=None,
closure=None, w_ann=None, forcename=None, qualname=None):
self.space = space
self.name = forcename or code.co_name
@@ -48,10 +50,12 @@
self.w_func_globals = w_globals # the globals dictionary
self.closure = closure # normally, list of Cell instances or None
self.defs_w = defs_w
- self.w_kw_defs = w_kw_defs
self.w_func_dict = None # filled out below if needed
self.w_module = None
self.w_ann = w_ann
+ #
+ if kw_defs_w is not None:
+ self.init_kwdefaults_dict(kw_defs_w)
def __repr__(self):
# return "function %s.%s" % (self.space, self.name)
@@ -379,14 +383,29 @@
def fset_func_kwdefaults(self, space, w_new):
if space.is_w(w_new, space.w_None):
- w_new = None
- elif not space.isinstance_w(w_new, space.w_dict):
- raise oefmt(space.w_TypeError, "__kwdefaults__ must be a dict")
- self.w_kw_defs = w_new
+ self.w_kw_defs = None
+ else:
+ if not space.isinstance_w(w_new, space.w_dict):
+ raise oefmt(space.w_TypeError, "__kwdefaults__ must be a dict")
+ w_instance = self.init_kwdefaults_dict()
+ w_instance.setdict(space, w_new)
+ self.w_kw_defs = w_instance.getdict(space)
def fdel_func_kwdefaults(self, space):
self.w_kw_defs = None
+ def init_kwdefaults_dict(self, kw_defs_w=[]):
+ # use the mapdict logic to get at least not-too-bad JIT code
+ # from function calls with default values of kwonly arguments
+ space = self.space
+ w_class = space.fromcache(KwDefsClassCache).w_class
+ w_instance = space.call_function(w_class)
+ for w_name, w_value in kw_defs_w:
+ attr = space.unicode_w(w_name).encode('utf-8')
+ w_instance.setdictvalue(space, attr, w_value)
+ self.w_kw_defs = w_instance.getdict(space)
+ return w_instance
+
def fget_func_doc(self, space):
if self.w_doc is None:
self.w_doc = self.code.getdocstring(space)
@@ -663,11 +682,12 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs_w, func.w_kw_defs, func.closure,
+ func.defs_w, None, func.closure,
None, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
+ self.w_kw_defs = func.w_kw_defs
def descr_builtinfunction__new__(space, w_subtype):
raise oefmt(space.w_TypeError,
@@ -685,3 +705,12 @@
else:
code = None
return isinstance(code, BuiltinCode)
+
+
+class KwDefsClassCache:
+ def __init__(self, space):
+ self.w_class = space.appexec([], """():
+ class KwDefs:
+ pass
+ return KwDefs
+ """)
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1235,15 +1235,15 @@
for i in range(len(names_w) - 1, -1, -1):
space.setitem(w_ann, names_w[i], self.popvalue())
defaultarguments = self.popvalues(posdefaults)
- w_kw_defs = None
+ kw_defs_w = None
if kwdefaults:
- w_kw_defs = space.newdict(strdict=True)
- for i in range(kwdefaults - 1, -1, -1):
- w_name = self.popvalue()
- w_def = self.popvalue()
- space.setitem(w_kw_defs, w_def, w_name)
+ kw_defs_w = []
+ for i in range(kwdefaults):
+ w_defvalue = self.popvalue()
+ w_defname = self.popvalue()
+ kw_defs_w.append((w_defname, w_defvalue))
fn = function.Function(space, codeobj, self.get_w_globals(), defaultarguments,
- w_kw_defs, freevars, w_ann, qualname=qualname)
+ kw_defs_w, freevars, w_ann, qualname=qualname)
self.pushvalue(space.wrap(fn))
def MAKE_FUNCTION(self, oparg, next_instr):
More information about the pypy-commit
mailing list