[pypy-svn] r9095 - in pypy/branch/dist-interpapp/pypy/interpreter: . test
hpk at codespeak.net
hpk at codespeak.net
Fri Feb 11 00:24:07 CET 2005
Author: hpk
Date: Fri Feb 11 00:24:07 2005
New Revision: 9095
Modified:
pypy/branch/dist-interpapp/pypy/interpreter/gateway.py
pypy/branch/dist-interpapp/pypy/interpreter/test/test_appinterp.py
Log:
handle default arguments for applevel functions
defined via appdef(). This involves some (very localized)
hacking at definition time but basically doesn't change
the semantics of the still existing "space.appexec()".
I.e. if you provide:
app = appdef("app(x, y=1)", """
return x + y
""")
the 'app' hook will be compiled from generated sourcode
(more or less with pure string-juggling with some help of
py.code.Source() :-)
The resulting interplevel hook for the app-level definition
(as seen by the translator) looks like this:
def app(space, w_x, w_y=None):
if w_y is None:
w_y = space.wrap(1)
pypyco = PyCode(space)._from_code(newco)
w_glob = space.newdict([])
frame = pypyco.create_frame(space, w_glob)
frame.setfastscope([w_x, w_y])
return frame.run()
which looks pretty reasonable compared to gateway.app2interp
and friends, doesn't it?
Modified: pypy/branch/dist-interpapp/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/dist-interpapp/pypy/interpreter/gateway.py (original)
+++ pypy/branch/dist-interpapp/pypy/interpreter/gateway.py Fri Feb 11 00:24:07 2005
@@ -645,18 +645,6 @@
# and now for something completly different ...
#
-# the following function might just go away
-#def preparesource(source):
-# from pypy.tool.pytestsupport import py # aehem
-# argdecl, source = source.split(':', 1)
-# argdecl = argdecl.strip()
-# if not argdecl.startswith('(') or not argdecl.endswith(')'):
-# raise SyntaxError("incorrect exec_with header\n%s" % source)
-#
-# newco = peparesource_funcdecl(source, argdecl+'(')
-# argnames = argdecl[1:-1].strip().split(',')
-# return newco, argnames
-
def preparesource(source, funcdecl):
from pypy.tool.pytestsupport import py
@@ -669,24 +657,56 @@
return d[funcdecl[:i]].func_code
def appdef(funcdecl, source):
- from pypy.tool.pytestsupport import py
from pypy.interpreter.pycode import PyCode
+ from pypy.tool.pytestsupport import py
newco = preparesource(source, funcdecl)
funcname, decl = funcdecl.split('(', 1)
decl = decl.strip()[:-1]
- wargnames = ["w_%s" % x.strip() for x in decl[:-1].split(',')]
- wdecl = ", ".join(wargnames)
- source = py.code.Source("""
+ wfuncdecl, wfastscope, defaulthandlingsource = specialargparse(decl)
+ source = py.code.Source("""\
def %s(space, %s):
+ # HERE we inject the defhandlingsource below
pypyco = PyCode(space)._from_code(newco)
w_glob = space.newdict([])
frame = pypyco.create_frame(space, w_glob)
frame.setfastscope([%s])
return frame.run()
- """ % (funcname, wdecl, wdecl))
+ """ % (funcname, wfuncdecl, wfastscope))
+ source.lines[1:2] = defaulthandlingsource.indent().lines
+ print str(source)
glob = {
'newco' : newco,
'PyCode': PyCode,
}
exec source.compile() in glob
return glob[funcname]
+
+def specialargparse(decl):
+ from pypy.tool.pytestsupport import py # for code generation
+ wfuncargs = []
+ wfastnames = []
+ defaultargs = []
+ for name in decl.split(','):
+ name = "w_%s" % name.strip()
+ if '=' in name:
+ name, value = name.split('=')
+ wfastnames.append(name)
+ defaultargs.append((name, value))
+ name += "=None"
+ else:
+ assert not defaultargs, "posarg follows defaultarg"
+ wfastnames.append(name)
+ wfuncargs.append(name)
+
+ # now we generate some nice code for default arg checking
+ # (which does not imply that the code doing it is nice :-)
+ defaulthandlingsource = py.code.Source()
+ while defaultargs:
+ name, value = defaultargs.pop()
+ defaulthandlingsource = defaulthandlingsource.putaround("""\
+ if %s is None:
+ %s = space.wrap(%s)
+ """ % (name, name, value), "")
+ wfuncdecl = ", ".join(wfuncargs)
+ wfastdecl = ", ".join(wfastnames)
+ return wfuncdecl, wfastdecl, defaulthandlingsource
Modified: pypy/branch/dist-interpapp/pypy/interpreter/test/test_appinterp.py
==============================================================================
--- pypy/branch/dist-interpapp/pypy/interpreter/test/test_appinterp.py (original)
+++ pypy/branch/dist-interpapp/pypy/interpreter/test/test_appinterp.py Fri Feb 11 00:24:07 2005
@@ -31,3 +31,12 @@
assert app.func_name == 'app'
w_result = app(space, space.wrap(41), space.wrap(1))
assert space.eq_w(w_result, space.wrap(42))
+
+def test_applevel_withdefault(space):
+ app = appdef("app(x,y=1)", """
+ return x + y
+ """)
+ assert app.func_name == 'app'
+ w_result = app(space, space.wrap(41))
+ assert space.eq_w(w_result, space.wrap(42))
+
More information about the Pypy-commit
mailing list