[pypy-svn] r8227 - in pypy/branch/src-pytest/pypy: appspace interpreter objspace/flow objspace/std tool translator translator/java translator/java/test translator/test translator/tool
pedronis at codespeak.net
pedronis at codespeak.net
Wed Jan 12 15:31:13 CET 2005
Author: pedronis
Date: Wed Jan 12 15:31:13 2005
New Revision: 8227
Added:
pypy/branch/src-pytest/pypy/appspace/struct.py
- copied unchanged from r8225, pypy/trunk/src/pypy/appspace/struct.py
pypy/branch/src-pytest/pypy/translator/geninterplevel.py (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/geninterplevel.py
pypy/branch/src-pytest/pypy/translator/java/ (props changed)
- copied from r8225, pypy/trunk/src/pypy/translator/java/
pypy/branch/src-pytest/pypy/translator/java/PyBool.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/PyBool.java
pypy/branch/src-pytest/pypy/translator/java/PyInt.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/PyInt.java
pypy/branch/src-pytest/pypy/translator/java/PyList.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/PyList.java
pypy/branch/src-pytest/pypy/translator/java/PyObject.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/PyObject.java
pypy/branch/src-pytest/pypy/translator/java/PySequence.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/PySequence.java
pypy/branch/src-pytest/pypy/translator/java/PyTuple.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/PyTuple.java
pypy/branch/src-pytest/pypy/translator/java/TypeError.java (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/TypeError.java
pypy/branch/src-pytest/pypy/translator/java/__init__.py (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/__init__.py
pypy/branch/src-pytest/pypy/translator/java/autopath.py (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/autopath.py
pypy/branch/src-pytest/pypy/translator/java/genjava.py (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/genjava.py
pypy/branch/src-pytest/pypy/translator/java/test/ (props changed)
- copied from r8225, pypy/trunk/src/pypy/translator/java/test/
pypy/branch/src-pytest/pypy/translator/java/test/__init__.py
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/test/__init__.py
pypy/branch/src-pytest/pypy/translator/java/test/autopath.py (props changed)
- copied unchanged from r8225, pypy/trunk/src/pypy/translator/java/test/autopath.py
pypy/branch/src-pytest/pypy/translator/java/test/test_javatrans.py (contents, props changed)
- copied, changed from r8225, pypy/trunk/src/pypy/translator/java/test/test_javatrans.py
Modified:
pypy/branch/src-pytest/pypy/appspace/_formatting.py
pypy/branch/src-pytest/pypy/appspace/md5.py
pypy/branch/src-pytest/pypy/interpreter/error.py
pypy/branch/src-pytest/pypy/objspace/flow/model.py
pypy/branch/src-pytest/pypy/objspace/flow/objspace.py
pypy/branch/src-pytest/pypy/objspace/std/longobject.py
pypy/branch/src-pytest/pypy/objspace/std/objspace.py
pypy/branch/src-pytest/pypy/tool/hack.py
pypy/branch/src-pytest/pypy/translator/genc.h
pypy/branch/src-pytest/pypy/translator/genc.py
pypy/branch/src-pytest/pypy/translator/gencl.py
pypy/branch/src-pytest/pypy/translator/genrpy.py
pypy/branch/src-pytest/pypy/translator/test/test_ctrans.py
pypy/branch/src-pytest/pypy/translator/tool/buildpyxmodule.py
Log:
merged changes happened on the head into src-pytest branch
Modified: pypy/branch/src-pytest/pypy/appspace/_formatting.py
==============================================================================
--- pypy/branch/src-pytest/pypy/appspace/_formatting.py (original)
+++ pypy/branch/src-pytest/pypy/appspace/_formatting.py Wed Jan 12 15:31:13 2005
@@ -225,7 +225,7 @@
class FloatFFormatter(FloatFormatter):
def _format(self, v):
if v/1e25 > 1e25:
- return floatGFormatter('g', self.flags, self.width,
+ return FloatGFormatter('g', self.flags, self.width,
self.prec, self.value).format()
ds, k = flonum2digits(v)
digits = self.fDigits(ds, k)
Modified: pypy/branch/src-pytest/pypy/appspace/md5.py
==============================================================================
--- pypy/branch/src-pytest/pypy/appspace/md5.py (original)
+++ pypy/branch/src-pytest/pypy/appspace/md5.py Wed Jan 12 15:31:13 2005
@@ -32,6 +32,7 @@
__date__ = '2004-11-17'
__version__ = 0.91 # Modernised by J. Hallén and L. Creighton for Pypy
+__metaclass__ = type # or genrpy won't work
import struct, copy
Modified: pypy/branch/src-pytest/pypy/interpreter/error.py
==============================================================================
--- pypy/branch/src-pytest/pypy/interpreter/error.py (original)
+++ pypy/branch/src-pytest/pypy/interpreter/error.py Wed Jan 12 15:31:13 2005
@@ -21,6 +21,7 @@
"""
def __init__(self, w_type, w_value, tb=None):
+ assert w_type is not None, w_value
self.w_type = w_type
self.w_value = w_value
self.application_traceback = tb
Modified: pypy/branch/src-pytest/pypy/objspace/flow/model.py
==============================================================================
--- pypy/branch/src-pytest/pypy/objspace/flow/model.py (original)
+++ pypy/branch/src-pytest/pypy/objspace/flow/model.py Wed Jan 12 15:31:13 2005
@@ -153,7 +153,7 @@
if (r.startswith('<') and r.endswith('>') and
hasattr(self.value, '__name__')):
r = '%s %s' % (type(self.value).__name__, self.value.__name__)
- elif len(r) > 30:
+ elif len(r) > 60 or (len(r) > 30 and type(self.value) is not str):
r = r[:20] + '...' + r[-8:]
return '(%s)' % r
Modified: pypy/branch/src-pytest/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/branch/src-pytest/pypy/objspace/flow/objspace.py (original)
+++ pypy/branch/src-pytest/pypy/objspace/flow/objspace.py Wed Jan 12 15:31:13 2005
@@ -34,6 +34,12 @@
AssertionError]:
clsname = exc.__name__
setattr(self, 'w_'+clsname, Constant(exc))
+ # the following exceptions are the ones that should not show up
+ # during flow graph construction; they are triggered by
+ # non-R-Pythonic constructs or real bugs like typos.
+ for exc in [NameError, UnboundLocalError]:
+ clsname = exc.__name__
+ setattr(self, 'w_'+clsname, None)
self.specialcases = {}
#self.make_builtins()
#self.make_sys()
Modified: pypy/branch/src-pytest/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/branch/src-pytest/pypy/objspace/std/longobject.py (original)
+++ pypy/branch/src-pytest/pypy/objspace/std/longobject.py Wed Jan 12 15:31:13 2005
@@ -19,29 +19,6 @@
registerimplementation(W_LongObject)
-# int-to-long delegation
-def delegate__Int(space, w_intobj):
- return W_LongObject(space, long(w_intobj.intval))
-delegate__Int.result_class = W_LongObject
-delegate__Int.priority = PRIORITY_CHANGE_TYPE
-
-# long-to-int delegation
-def delegate__Long(space, w_longobj):
- if -sys.maxint-1 <= w_longobj.longval <= sys.maxint:
- return W_IntObject(space, int(w_longobj.longval))
- else:
- # note the 'return' here -- hack
- return FailedToImplement(space.w_OverflowError,
- space.wrap("long int too large to convert to int"))
-delegate__Long.result_class = W_IntObject
-delegate__Long.priority = PRIORITY_CHANGE_TYPE
-delegate__Long.can_fail = True
-
-## # long-to-float delegation
-## def delegate__Long(space, w_longobj):
-## return W_FloatObject(space, float(w_longobj.longval))
-## delegate__Long.result_class = W_FloatObject
-## delegate__Long.priority = PRIORITY_CHANGE_TYPE
# long__Long is supposed to do nothing, unless it has
# a derived long object, where it should return
@@ -224,3 +201,36 @@
register_all(vars())
+
+# delegations must be registered manually because we have more than one
+# long-to-something delegation
+
+# int-to-long delegation
+def delegate_from_int(space, w_intobj):
+ return W_LongObject(space, long(w_intobj.intval))
+delegate_from_int.result_class = W_LongObject
+delegate_from_int.priority = PRIORITY_CHANGE_TYPE
+
+StdObjSpace.delegate.register(delegate_from_int, W_IntObject)
+
+# long-to-int delegation
+def delegate_to_int(space, w_longobj):
+ if -sys.maxint-1 <= w_longobj.longval <= sys.maxint:
+ return W_IntObject(space, int(w_longobj.longval))
+ else:
+ # note the 'return' here -- hack
+ return FailedToImplement(space.w_OverflowError,
+ space.wrap("long int too large to convert to int"))
+delegate_to_int.result_class = W_IntObject
+delegate_to_int.priority = PRIORITY_CHANGE_TYPE
+delegate_to_int.can_fail = True
+
+StdObjSpace.delegate.register(delegate_to_int, W_LongObject)
+
+# long-to-float delegation
+def delegate_to_float(space, w_longobj):
+ return W_FloatObject(space, float(w_longobj.longval))
+delegate_to_float.result_class = W_FloatObject
+delegate_to_float.priority = PRIORITY_CHANGE_TYPE
+
+StdObjSpace.delegate.register(delegate_to_float, W_LongObject)
Modified: pypy/branch/src-pytest/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/src-pytest/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/src-pytest/pypy/objspace/std/objspace.py Wed Jan 12 15:31:13 2005
@@ -243,12 +243,12 @@
return W_ListObject(self, wrappeditems)
if isinstance(x, long):
return W_LongObject(self, x)
- if isinstance(x, complex):
- # XXX is this right?
- c = self.getitem(self.w_builtins, self.wrap("complex"))
- return self.call_function(c,
- self.wrap(x.real),
- self.wrap(x.imag))
+## if isinstance(x, complex):
+## # XXX is this right? YYY no, this is wrong right now (CT)
+## c = self.getitem(self.w_builtins, self.wrap("complex"))
+## return self.call_function(c,
+## self.wrap(x.real),
+## self.wrap(x.imag))
if isinstance(x, BaseWrappable):
w_result = x.__spacebind__(self)
#print 'wrapping', x, '->', w_result
Modified: pypy/branch/src-pytest/pypy/tool/hack.py
==============================================================================
--- pypy/branch/src-pytest/pypy/tool/hack.py (original)
+++ pypy/branch/src-pytest/pypy/tool/hack.py Wed Jan 12 15:31:13 2005
@@ -2,7 +2,7 @@
import new, sys
-if sys.version_info > (2, 2):
+if sys.version_info >= (2, 3):
def func_with_new_name(func, newname):
f = new.function(func.func_code, func.func_globals,
Modified: pypy/branch/src-pytest/pypy/translator/genc.h
==============================================================================
--- pypy/branch/src-pytest/pypy/translator/genc.h (original)
+++ pypy/branch/src-pytest/pypy/translator/genc.h Wed Jan 12 15:31:13 2005
@@ -199,6 +199,11 @@
#if defined(USE_CALL_TRACE)
+#define TRACE_CALL __f, __tstate,
+#define TRACE_ARGS PyFrameObject *__f, PyThreadState *__tstate,
+#define TRACE_CALL_VOID __f, __tstate
+#define TRACE_ARGS_VOID PyFrameObject *__f, PyThreadState *__tstate
+
#define FAIL(err) { __f->f_lineno = __f->f_code->co_firstlineno = __LINE__; goto err; }
#define FUNCTION_HEAD(signature, self, args, names, file, line) \
@@ -215,6 +220,11 @@
#else /* !defined(USE_CALL_TRACE) */
+#define TRACE_CALL /* nothing */
+#define TRACE_ARGS /* nothing */
+#define TRACE_CALL_VOID /* nothing */
+#define TRACE_ARGS_VOID void
+
#define FAIL(err) { goto err; }
#define FUNCTION_HEAD(signature, self, args, names, file, line)
Modified: pypy/branch/src-pytest/pypy/translator/genc.py
==============================================================================
--- pypy/branch/src-pytest/pypy/translator/genc.py (original)
+++ pypy/branch/src-pytest/pypy/translator/genc.py Wed Jan 12 15:31:13 2005
@@ -38,8 +38,6 @@
class GenC:
MODNAMES = {}
- # XXX - I don't know how to make a macro do this.. so..
- USE_CALL_TRACE = True
def __init__(self, f, translator, modname=None, f2=None, f2name=None):
self.f = f
@@ -454,8 +452,6 @@
'entrypoint': self.nameof(self.translator.functions[0]),
}
# header
- if self.USE_CALL_TRACE:
- print >> f, '#define USE_CALL_TRACE'
print >> f, self.C_HEADER
# function implementations
@@ -510,9 +506,9 @@
self.gen_global_declarations()
# print header
- name = self.nameof(func)
- assert name.startswith('gfunc_')
- f_name = 'f_' + name[6:]
+ cname = self.nameof(func)
+ assert cname.startswith('gfunc_')
+ f_name = 'f_' + cname[6:]
# collect all the local variables
graph = self.translator.getflowgraph(func)
@@ -540,22 +536,31 @@
fast_set = dict(zip(fast_args, fast_args))
declare_fast_args = [('PyObject *' + a) for a in fast_args]
- if self.USE_CALL_TRACE:
- declare_fast_args[:0] = ['PyFrameObject *__f', 'PyThreadState *__tstate']
+ if declare_fast_args:
+ declare_fast_args = 'TRACE_ARGS ' + ', '.join(declare_fast_args)
+ else:
+ declare_fast_args = 'TRACE_ARGS_VOID'
+ fast_function_header = ('static PyObject *\n'
+ '%s(%s)' % (fast_name, declare_fast_args))
- print >> f, 'static PyObject *'
- print >> f, '%s(%s);' % (fast_name, ', '.join(declare_fast_args))
+ print >> f, fast_function_header + ';' # forward
print >> f
print >> f, 'static PyObject *'
- print >> f, '%s(PyObject* self, PyObject* args)' % (f_name,)
+ print >> f, '%s(PyObject* self, PyObject* args, PyObject* kwds)' % (
+ f_name,)
print >> f, '{'
print >> f, '\tFUNCTION_HEAD(%s, %s, args, %s, __FILE__, __LINE__ - 2)' % (
- c_string('%s(%s)' % (name, ', '.join(name_of_defaults))),
- name,
+ c_string('%s(%s)' % (cname, ', '.join(name_of_defaults))),
+ cname,
'(%s)' % (', '.join(map(c_string, name_of_defaults) + ['NULL']),),
)
+ kwlist = ['"%s"' % name for name in
+ func.func_code.co_varnames[:func.func_code.co_argcount]]
+ kwlist.append('0')
+ print >> f, '\tstatic char* kwlist[] = {%s};' % (', '.join(kwlist),)
+
if fast_args:
print >> f, '\tPyObject *%s;' % (', *'.join(fast_args))
print >> f
@@ -586,24 +591,27 @@
print >> f, '\t%s = %s;' % (
positional_args[min_number_of_args+i],
name_of_defaults[i])
- lst = ['args',
- '"%s"' % func.__name__,
- '%d' % min_number_of_args,
- '%d' % len(positional_args),
+ fmt = 'O'*min_number_of_args
+ if min_number_of_args < len(positional_args):
+ fmt += '|' + 'O'*(len(positional_args)-min_number_of_args)
+ lst = ['args', 'kwds',
+ '"%s:%s"' % (fmt, func.__name__),
+ 'kwlist',
]
lst += ['&' + a.name for a in positional_args]
- print >> f, '\tif (!PyArg_UnpackTuple(%s))' % ', '.join(lst),
+ print >> f, '\tif (!PyArg_ParseTupleAndKeywords(%s))' % ', '.join(lst),
print >> f, tail
call_fast_args = list(fast_args)
- if self.USE_CALL_TRACE:
- call_fast_args[:0] = ['__f', '__tstate']
- print >> f, '\treturn %s(%s);' % (fast_name, ', '.join(call_fast_args))
+ if call_fast_args:
+ call_fast_args = 'TRACE_CALL ' + ', '.join(call_fast_args)
+ else:
+ call_fast_args = 'TRACE_CALL_VOID'
+ print >> f, '\treturn %s(%s);' % (fast_name, call_fast_args)
print >> f, '}'
print >> f
- print >> f, 'static PyObject *'
- print >> f, '%s(%s)' % (fast_name, ', '.join(declare_fast_args))
+ print >> f, fast_function_header
print >> f, '{'
fast_locals = [arg for arg in localnames if arg not in fast_set]
@@ -630,8 +638,9 @@
print >> f, '}'
# print the PyMethodDef
- print >> f, 'static PyMethodDef ml_%s = { "%s", %s, METH_VARARGS };' % (
- name, func.__name__, f_name)
+ print >> f, ('static PyMethodDef ml_%s = {\n'
+ ' "%s", (PyCFunction)%s, METH_VARARGS|METH_KEYWORDS };' % (
+ cname, func.__name__, f_name))
print >> f
if not self.translator.frozen:
Modified: pypy/branch/src-pytest/pypy/translator/gencl.py
==============================================================================
--- pypy/branch/src-pytest/pypy/translator/gencl.py (original)
+++ pypy/branch/src-pytest/pypy/translator/gencl.py Wed Jan 12 15:31:13 2005
@@ -193,7 +193,7 @@
return "'last-exc-value"
else:
return "#<%r>" % (val,)
- def emitcode(self):
+ def emitcode(self, public=True):
import sys
from cStringIO import StringIO
out = StringIO()
Modified: pypy/branch/src-pytest/pypy/translator/genrpy.py
==============================================================================
--- pypy/branch/src-pytest/pypy/translator/genrpy.py (original)
+++ pypy/branch/src-pytest/pypy/translator/genrpy.py Wed Jan 12 15:31:13 2005
@@ -10,22 +10,53 @@
that globals are constants, for instance. This definition is not
exact and might change.
-This module is very much under construction and not yet usable for much
-more than testing.
+This module appears to be already quite usable.
+But I need to ask how we want to integrate it.
+
+XXX open questions:
+- do we wantamoduleperapp-spaceoperation?
+- do we want to auto-generate stuff?
+- do we want to create code that is more similar to the app code?
+- do we want to create specialized code for constants?
+- do we want to use small tail-functions instead of goto?
+- do we want to inline small functions?
+- do we want to translate non-rpythonic code as well?
"""
-from pypy.objspace.flow.model import traverse
-from pypy.objspace.flow import FlowObjSpace
-from pypy.objspace.flow.model import FunctionGraph, Block, Link, Variable, Constant
+from __future__ import generators
+import autopath, os, sys, exceptions
+from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
+from pypy.objspace.flow.model import FunctionGraph, Block, Link
from pypy.objspace.flow.model import last_exception, last_exc_value
-from pypy.translator.simplify import simplify_graph
+from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
+from pypy.translator.simplify import remove_direct_loops
+from pypy.interpreter.pycode import CO_VARARGS
+from pypy.annotation import model as annmodel
+from types import FunctionType, CodeType
from pypy.interpreter.error import OperationError
-from types import FunctionType
+from pypy.objspace.std.restricted_int import r_int, r_uint
from pypy.translator.translator import Translator
+from pypy.objspace.std import StdObjSpace
+from pypy.objspace.flow import FlowObjSpace
+
+from pypy.interpreter.gateway import app2interp, interp2app
+
-import sys
+# ____________________________________________________________
+def c_string(s):
+ return '"%s"' % (s.replace('\\', '\\\\').replace('"', '\"'),)
+
+def uniquemodulename(name, SEEN={}):
+ # never reuse the same module name within a Python session!
+ i = 0
+ while True:
+ i += 1
+ result = '%s_%d' % (name, i)
+ if result not in SEEN:
+ SEEN[result] = True
+ return result
def ordered_blocks(graph):
# collect all blocks
@@ -49,65 +80,167 @@
# print ofs, txt, block
return [block for ofs, txt, block in allblocks]
+class UniqueList(list):
+ def __init__(self, *args, **kwds):
+ list.__init__(self, *args, **kwds)
+ self.dic = {}
+ def append(self, arg):
+ try:
+ self.dic[arg]
+ except KeyError:
+ self.dic[arg] = 1
+ list.append(self, arg)
+ except TypeError: # not hashable
+ if arg not in self:
+ list.append(self, arg)
+
class GenRpy:
- def __init__(self, f, translator, modname=None):
- self.f = f
+ def __init__(self, translator, modname=None):
self.translator = translator
- self.modname = (modname or
- translator.functions[0].__name__)
- self.rpynames = {Constant(None).key: 'w(None)',
- Constant(False).key: 'w(False)',
- Constant(True).key: 'w(True)',
+ self.modname = self.trans_funcname(modname or
+ uniquemodulename(translator.functions[0].__name__))
+ self.rpynames = {Constant(None).key: 'space.w_None',
+ Constant(False).key: 'space.w_False',
+ Constant(True).key: 'space.w_True',
}
self.seennames = {}
- self.initcode = [] # list of lines for the module's initxxx()
- self.latercode = [] # list of generators generating extra lines
+ u = UniqueList
+ self.initcode = u() # list of lines for the module's initxxx()
+ self.latercode = u() # list of generators generating extra lines
# for later in initxxx() -- for recursive
# objects
self.globaldecl = []
self.globalobjects = []
self.pendingfunctions = []
+ self.currentfunc = None
+ self.debugstack = () # linked list of nested nameof()
# special constructors:
self.has_listarg = {}
for name in "newtuple newlist newdict newstring".split():
self.has_listarg[name] = name
- self.current_globals = {}
- self.glob_names = []
- self.glob_values = []
-
- self.gen_source()
-
- def adjust_namespace(self):
- """ inspect the globals of self.current_func and build a searchable list
- of the globals.
- """
- g = self.current_func.func_globals
- if g is self.current_globals:
- return
- self.current_globals = g
- order = [(value, key) for key, value in g.items()]
- order.sort()
- self.glob_names = [key for value, key in order]
- self.glob_values = [value for value, key in order]
-
- def find_global_name(self, obj):
- for i in xrange(len(self.glob_values)):
- if self.glob_values[i] is obj:
- return self.glob_names[i]
- return None
+ # XXX I guess it is cleaner to use the flow space?
+ # we just want to look into the operations,
+ # but we don't break into the implementation.
+ # Or should it be the base space, ARMIN?
+ #self.space = StdObjSpace() # for introspection
+ self.space = FlowObjSpace() # for introspection
- def nameof(self, obj):
+ self.use_fast_call = False
+
+ def expr(self, v, localnames, wrapped = True):
+ if isinstance(v, Variable):
+ n = v.name
+ if n.startswith("v") and n[1:].isdigit():
+ ret = localnames.get(v.name)
+ if not ret:
+ if wrapped:
+ localnames[v.name] = ret = "w_%d" % len(localnames)
+ else:
+ localnames[v.name] = ret = "v%d" % len(localnames)
+ return ret
+ elif isinstance(v, Constant):
+ return self.nameof(v.value,
+ debug=('Constant in the graph of', self.currentfunc))
+ else:
+ raise TypeError, "expr(%r)" % (v,)
+
+ def arglist(self, args, localnames):
+ res = [self.expr(arg, localnames) for arg in args]
+ return ", ".join(res)
+
+ def oper(self, op, localnames):
+ if op.opname == "simple_call":
+ v = op.args[0]
+ exv = self.expr(v, localnames)
+ if exv.startswith("space.") and not exv.startswith("space.w_"):
+ # it is a space method
+ fmt = "%(res)s = %(func)s(%(args)s)"
+ else:
+ # default for a spacecall:
+ fmt = ("_tup = space.newtuple([%(args)s])\n"
+ "%(res)s = space.call(%(func)s, _tup)")
+ # see if we can optimize for a fast call.
+ # we justdo the very simple ones.
+ if self.use_fast_call and (isinstance(v, Constant)
+ and exv.startswith('gfunc_')):
+ func = v.value
+ if (not func.func_code.co_flags & CO_VARARGS) and (
+ func.func_defaults is None):
+ fmt = "%(res)s = fastf_%(func)s(space, %(args)s)"
+ exv = exv[6:]
+ return fmt % {"res" : self.expr(op.result, localnames),
+ "func": exv,
+ "args": self.arglist(op.args[1:], localnames) }
+ if op.opname in self.has_listarg:
+ fmt = "%s = %s([%s])"
+ else:
+ fmt = "%s = %s(%s)"
+ # special case is_true
+ wrapped = op.opname != "is_true"
+ oper = "space.%s" % op.opname
+ return fmt % (self.expr(op.result, localnames, wrapped), oper,
+ self.arglist(op.args, localnames))
+
+ def large_assignment(self, left, right, margin=65):
+ expr = "(%s) = (%s)" % (", ".join(left), ", ".join(right))
+ pieces = expr.split(",")
+ res = [pieces.pop(0)]
+ for piece in pieces:
+ if len(res[-1])+len(piece)+1 > margin:
+ res[-1] += ","
+ res.append(piece)
+ else:
+ res[-1] += (","+piece)
+ return res
+
+ def large_initialize(self, vars, margin=65):
+ res = []
+ nonestr = "None"
+ margin -= len(nonestr)
+ for var in vars:
+ ass = var+"="
+ if not res or len(res[-1]) >= margin:
+ res.append(ass)
+ res[-1] += ass
+ res = [line + nonestr for line in res]
+ return res
+
+ def gen_link(self, link, localvars, blocknum, block, linklocalvars=None):
+ "Generate the code to jump across the given Link."
+ linklocalvars = linklocalvars or {}
+ left, right = [], []
+ for a1, a2 in zip(link.args, link.target.inputargs):
+ if a1 in linklocalvars:
+ src = linklocalvars[a1]
+ else:
+ src = self.expr(a1, localvars)
+ left.append(self.expr(a2, localvars))
+ right.append(src)
+ txt = "%s = %s" % (", ".join(left), ", ".join(right))
+ if len(txt) <= 65: # arbitrary
+ yield txt
+ else:
+ for line in self.large_assignment(left, right):
+ yield line
+ goto = blocknum[link.target]
+ yield 'goto = %d' % goto
+ if goto <= blocknum[block]:
+ yield 'continue'
+
+ def nameof(self, obj, debug=None, namehint=None):
key = Constant(obj).key
try:
return self.rpynames[key]
except KeyError:
- #name = "w(%s)" % str(obj)
- #self.rpynames[key] = name
- #return name
+ if debug:
+ stackentry = debug, obj
+ else:
+ stackentry = obj
+ self.debugstack = (self.debugstack, stackentry)
if (type(obj).__module__ != '__builtin__' and
not isinstance(obj, type)): # skip user-defined metaclasses
# assume it's a user defined thingy
@@ -120,26 +253,37 @@
if meth:
break
else:
- raise Exception, "nameof(%r) in %r" % (obj, self.current_func)
- name = meth(obj)
+ raise Exception, "nameof(%r)" % (obj,)
+
+ code=meth.im_func.func_code
+ if namehint and 'namehint' in code.co_varnames[:code.co_argcount]:
+ name = meth(obj, namehint=namehint)
+ else:
+ name = meth(obj)
+ self.debugstack, x = self.debugstack
+ assert x is stackentry
self.rpynames[key] = name
return name
def uniquename(self, basename):
+ basename = basename.translate(C_IDENTIFIER)
n = self.seennames.get(basename, 0)
self.seennames[basename] = n+1
if n == 0:
self.globalobjects.append(basename)
- self.globaldecl.append('static PyObject *%s;' % (basename,))
+ self.globaldecl.append('# global object %s' % (basename,))
return basename
else:
return self.uniquename('%s_%d' % (basename, n))
def nameof_object(self, value):
if type(value) is not object:
- raise Exception, "nameof(%r) in %r" % (value, self.current_func)
+ #raise Exception, "nameof(%r) in %r" % (value, self.currentfunc)
+ name = self.uniquename('g_unknown_%r' % value)
+ self.initcode.append('# cannot build %s as %r' % (name, object))
+ return name
name = self.uniquename('g_object')
- self.initcode.append('INITCHK(%s = PyObject_CallFunction((PyObject*)&PyBaseObject_Type, ""))'%name)
+ self.initcode.append('m.%s = object()'%name)
return name
def nameof_module(self, value):
@@ -148,44 +292,75 @@
value.__file__.endswith('.py') or
value.__file__.endswith('.pyo')), \
"%r is not a builtin module (probably :)"%value
- name = self.uniquename('mod%s'%value.__name__)
- self.initcode.append('INITCHK(%s = PyImport_ImportModule("%s"))'%(name, value.__name__))
+ name = self.uniquename('mod_%s'%value.__name__)
+ self.initcode.append('import %s as _tmp' % value.__name__)
+ self.initcode.append('m.%s = space.wrap(_tmp)' % (name))
return name
def nameof_int(self, value):
- return "w(%d)" % value
+ if value >= 0:
+ name = 'gi_%d' % value
+ else:
+ name = 'gim_%d' % abs(value)
+ name = self.uniquename(name)
+ self.initcode.append('m.%s = space.newint(%d)' % (name, value))
+ return name
def nameof_long(self, value):
+ # allow short longs only, meaning they
+ # must fit into a machine word.
+ assert (sys.maxint*2+1)&value==value, "your literal long is too long"
# assume we want them in hex most of the time
if value < 256L:
- return "%dL" % value
+ s = "%dL" % value
+ else:
+ s = "0x%08xL" % value
+ if value >= 0:
+ name = 'glong_%s' % s
else:
- return "0x%08xL" % value
+ name = 'glongm_%d' % abs(value)
+ name = self.uniquename(name)
+ self.initcode.append('m.%s = space.wrap(%s) # XXX implement long!' % (name, s))
+ return name
def nameof_float(self, value):
- return "w(%s)" % value
-
+ name = 'gfloat_%s' % value
+ name = (name.replace('-', 'minus')
+ .replace('.', 'dot'))
+ name = self.uniquename(name)
+ self.initcode.append('m.%s = space.newfloat(%r)' % (name, value))
+ return name
+
def nameof_str(self, value):
- name = self.find_global_name(value)
- if name:
- return "w(%s)" % name
- return "w(%s)" % repr(value)
+ if [c for c in value if c<' ' or c>'~' or c=='"' or c=='\\']:
+ # non-printable string
+ namestr = repr(value)[1:-1]
+ else:
+ # printable string
+ namestr = value
+ if not namestr:
+ namestr = "_emptystr_"
+ name = self.uniquename('gs_' + namestr[:32])
+ # self.initcode.append('m.%s = space.newstring(%r)' % (name, value))
+ # ick! very unhandy
+ self.initcode.append('m.%s = space.wrap(%r)' % (name, value))
+ return name
def skipped_function(self, func):
# debugging only! Generates a placeholder for missing functions
# that raises an exception when called.
name = self.uniquename('gskippedfunc_' + func.__name__)
- self.globaldecl.append('static PyMethodDef ml_%s = { "%s", &skipped, METH_VARARGS };' % (name, name))
- self.initcode.append('INITCHK(%s = PyCFunction_New('
- '&ml_%s, NULL))' % (name, name))
- self.initcode.append('\tPy_INCREF(%s);' % name)
- self.initcode.append('\tPyCFunction_GET_SELF(%s) = %s;' % (name, name))
+ self.globaldecl.append('# global decl %s' % (name, ))
+ self.initcode.append('# build func %s' % name)
return name
- def nameof_function(self, func):
+ def trans_funcname(self, s):
+ return s.translate(C_IDENTIFIER)
+
+ def nameof_function(self, func, namehint=''):
printable_name = '(%s:%d) %s' % (
- func.func_globals.get('__name__', '?'),
+ self.trans_funcname(func.func_globals.get('__name__', '?')),
func.func_code.co_firstlineno,
func.__name__)
if self.translator.frozen:
@@ -197,10 +372,11 @@
func.func_doc.lstrip().startswith('NOT_RPYTHON')):
print "skipped", printable_name
return self.skipped_function(func)
- name = func.__name__
- self.initcode.append('INITCHK(%s = PyCFunction_New('
- '&ml_%s, NULL))' % (name, name))
- self.initcode.append('\t%s->ob_type = &PyGenCFunction_Type;' % name)
+ name = self.uniquename('gfunc_' + self.trans_funcname(
+ namehint + func.__name__))
+ f_name = 'f_' + name[6:]
+ self.initcode.append('from pypy.interpreter.gateway import interp2app')
+ self.initcode.append('m.%s = space.wrap(interp2app(%s))' % (name, f_name))
self.pendingfunctions.append(func)
return name
@@ -209,22 +385,20 @@
func = sm.__get__(42.5)
name = self.uniquename('gsm_' + func.__name__)
functionname = self.nameof(func)
- self.initcode.append('INITCHK(%s = PyCFunction_New('
- '&ml_%s, NULL))' % (name, functionname))
+ self.initcode.append('m.%s = space.wrap(%s)' % (name, functionname))
return name
def nameof_instancemethod(self, meth):
if meth.im_self is None:
# no error checking here
- return self.nameof(meth.im_func)
+ return self.nameof(meth.im_func, namehint="%s_" % meth.im_class.__name__)
else:
ob = self.nameof(meth.im_self)
func = self.nameof(meth.im_func)
typ = self.nameof(meth.im_class)
name = self.uniquename('gmeth_'+meth.im_func.__name__)
self.initcode.append(
- 'INITCHK(%s = gencfunc_descr_get(%s, %s, %s))'%(
- name, func, ob, typ))
+ '%s = space.getattr(%s, %s)'%(name, ob, func))
return name
def should_translate_attr(self, pbc, attr):
@@ -235,16 +409,13 @@
return False
else:
return "probably" # True
- if attr in ann.getpbcattrs(pbc):
- return True
classdef = ann.getuserclasses().get(pbc.__class__)
- if (classdef and
- classdef.about_attribute(attr) != annmodel.SomeImpossibleValue()):
+ if classdef and classdef.about_attribute(attr) is not None:
return True
return False
def later(self, gen):
- self.latercode.append(gen)
+ self.latercode.append((gen, self.debugstack))
def nameof_instance(self, instance):
name = self.uniquename('ginst_' + instance.__class__.__name__)
@@ -254,24 +425,67 @@
content.sort()
for key, value in content:
if self.should_translate_attr(instance, key):
- yield 'INITCHK(SETUP_INSTANCE_ATTR(%s, "%s", %s))' % (
- name, key, self.nameof(value))
- self.initcode.append('INITCHK(SETUP_INSTANCE(%s, %s))' % (
- name, cls))
+ yield 'space.setattr(%s, %s, %s)' % (
+ name, self.nameof(key), self.nameof(value))
+ if isinstance(instance, Exception):
+ # specialcase for exception instances: wrap them directly
+ self.initcode.append('_ins = %s()\n'
+ 'm.%s = space.wrap(_ins)' % (
+ instance.__class__.__name__, name))
+ else:
+ # this seems to hardly work with the faked stuff
+ self.initcode.append('from types import InstanceType')
+ self.initcode.append('w_InstanceType = space.wrap(InstanceType)')
+ self.initcode.append('_tup = space.newtuple([%s])\n'
+ 'm.%s = space.call(w_InstanceType, _tup)' % (
+ cls, name))
self.later(initinstance())
return name
def nameof_builtin_function_or_method(self, func):
- return "w(%s)" % func.__name__
+ if func.__self__ is None:
+ # builtin function
+ if hasattr(self.space, func.__name__):
+ return "space.%s" % func.__name__
+ # where does it come from? Python2.2 doesn't have func.__module__
+ for modname, module in sys.modules.items():
+ if hasattr(module, '__file__'):
+ if (module.__file__.endswith('.py') or
+ module.__file__.endswith('.pyc') or
+ module.__file__.endswith('.pyo')):
+ continue # skip non-builtin modules
+ if func is getattr(module, func.__name__, None):
+ break
+ else:
+ raise Exception, '%r not found in any built-in module' % (func,)
+ name = self.uniquename('gbltin_' + func.__name__)
+ if modname == '__builtin__':
+ self.initcode.append('m.%s = space.getattr(space.w_builtin, %s)'% (
+ name, self.nameof(func.__name__)))
+ else:
+ self.initcode.append('m.%s = space.getattr(%s, %s)' % (
+ name, self.nameof(module), self.nameof(func.__name__)))
+ else:
+ # builtin (bound) method
+ name = self.uniquename('gbltinmethod_' + func.__name__)
+ self.initcode.append('m.%s = space.getattr(%s, %s)' % (
+ name, self.nameof(func.__self__), self.nameof(func.__name__)))
+ return name
def nameof_classobj(self, cls):
if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'):
raise Exception, "%r should never be reached" % (cls,)
- metaclass = "&PyType_Type"
+ metaclass = "space.w_type"
+ name = self.uniquename('gcls_' + cls.__name__)
if issubclass(cls, Exception):
if cls.__module__ == 'exceptions':
- return 'w(%s)'%cls.__name__
+ if hasattr(self.space, "w_%s" % cls.__name__):
+ return 'space.w_%s'%cls.__name__
+ else:
+ self.initcode.append('m.%s = space.wrap(%s)' % (
+ name, cls.__name__))
+ return name
#else:
# # exceptions must be old-style classes (grr!)
# metaclass = "&PyClass_Type"
@@ -279,9 +493,13 @@
# pypy source uses old-style classes, to avoid strange problems.
if not isinstance(cls, type):
assert type(cls) is type(Exception)
- metaclass = "&PyClass_Type"
+ # self.initcode.append("import types\n"
+ # "m.classtype = space.wrap(types.ClassType)\n")
+ # metaclass = "m.classtype"
+ # XXX I cannot instantiate these.
+ # XXX using type instead, since we still inherit from exception
+ # XXX what is the future of classes in pypy?
- name = self.uniquename('gcls_' + cls.__name__)
basenames = [self.nameof(base) for base in cls.__bases__]
def initclassobj():
content = cls.__dict__.items()
@@ -293,34 +511,83 @@
continue
# XXX some __NAMES__ are important... nicer solution sought
#raise Exception, "unexpected name %r in class %s"%(key, cls)
+
+ # redirect value through class interface, in order to
+ # get methods instead of functions.
+ value = getattr(cls, key)
+
if isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen:
- print value
+ print "skipped staticmethod:", value
continue
if isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen:
- print value
+ print "skippedfunction:", value
continue
- yield 'INITCHK(SETUP_CLASS_ATTR(%s, "%s", %s))' % (
- name, key, self.nameof(value))
+ yield 'space.setattr(%s, %s, %s)' % (
+ name, self.nameof(key), self.nameof(value))
baseargs = ", ".join(basenames)
- if baseargs:
- baseargs = ', '+baseargs
- self.initcode.append('INITCHK(%s = PyObject_CallFunction((PyObject*) %s,'
- %(name, metaclass))
- self.initcode.append('\t\t"s(%s){}", "%s"%s))'
- %("O"*len(basenames), cls.__name__, baseargs))
+ self.initcode.append('_dic = space.newdict([])\n'
+ '_bases = space.newtuple([%(bases)s])\n'
+ '_args = space.newtuple([%(name)s, _bases, _dic])\n'
+ 'm.%(klass)s = space.call(%(meta)s, _args)'
+ % {"bases": baseargs,
+ "klass": name,
+ "name" : self.nameof(cls.__name__),
+ "meta" : metaclass} )
self.later(initclassobj())
return name
nameof_class = nameof_classobj # for Python 2.2
+ typename_mapping = {
+ object: 'space.w_object',
+ int: 'space.w_int',
+ long: 'space.w_long',
+ bool: 'space.w_bool',
+ list: 'space.w_list',
+ tuple: 'space.w_tuple',
+ dict: 'space.w_dict',
+ str: 'space.w_str',
+ float: 'space.w_float',
+ type(Exception()): 'space.wrap(types.InstanceType)',
+ type: 'space.w_type',
+ complex:'space.wrap(types.ComplexType)',
+ unicode:'space.w_unicode',
+ file: 'space.wrap(file)',
+ type(None): 'space.wrap(types.NoneType)',
+ CodeType: 'space.wrap(types.CodeType)',
+
+ ##r_int: 'space.w_int',
+ ##r_uint: 'space.w_int',
+
+ # XXX we leak 5 references here, but that's the least of the
+ # problems with this section of code
+ # type 'builtin_function_or_method':
+ type(len): 'space.wrap(types.FunctionType)',
+ # type 'method_descriptor':
+ # XXX small problem here:
+ # XXX with space.eval, we get <W_TypeObject(method)>
+ # XXX but with wrap, we get <W_TypeObject(instancemethod)>
+ type(list.append): 'eval_helper(space, "list.append")',
+ # type 'wrapper_descriptor':
+ type(type(None).__repr__): 'eval_helper(space, ".type(None).__repr__")',
+ # type 'getset_descriptor':
+ # XXX here we get <W_TypeObject(FakeDescriptor)>,
+ # while eval gives us <W_TypeObject(GetSetProperty)>
+ type(type.__dict__['__dict__']): 'eval_helper(space,'\
+ ' "type(type.__dict__[\'__dict__\'])")',
+ # type 'member_descriptor':
+ # XXX this does not work in eval!
+ # type(type.__dict__['__basicsize__']): "cannot eval type(type.__dict__['__basicsize__'])",
+ # XXX there seems to be no working support for member descriptors ???
+ type(type.__dict__['__basicsize__']): "space.wrap(type(type.__dict__['__basicsize__']))",
+ }
def nameof_type(self, cls):
- return "w(%s)" % cls.__name__ ##??
if cls in self.typename_mapping:
- return '(PyObject*) %s' % self.typename_mapping[cls]
+ return self.typename_mapping[cls]
assert cls.__module__ != '__builtin__', \
"built-in class %r not found in typename_mapping" % (cls,)
return self.nameof_classobj(cls)
@@ -328,9 +595,8 @@
def nameof_tuple(self, tup):
name = self.uniquename('g%dtuple' % len(tup))
args = [self.nameof(x) for x in tup]
- args.insert(0, '%d' % len(tup))
args = ', '.join(args)
- self.initcode.append('INITCHK(%s = PyTuple_Pack(%s))' % (name, args))
+ self.initcode.append('m.%s = space.newtuple([%s])' % (name, args))
return name
def nameof_list(self, lis):
@@ -338,32 +604,23 @@
def initlist():
for i in range(len(lis)):
item = self.nameof(lis[i])
- yield '\tPy_INCREF(%s);' % item
- yield '\tPyList_SET_ITEM(%s, %d, %s);' % (name, i, item)
- self.initcode.append('INITCHK(%s = PyList_New(%d))' % (name, len(lis)))
+ yield 'space.setitem(%s, %s, %s);' % (
+ name, self.nameof(i), self.nameof(item))
+ self.initcode.append('m.%s = space.newlist(%s)' % (name, self.nameof(0)))
+ self.initcode.append('m.%s = space.mul(%s, %s)' % (name, name, self.nameof(len(lis))))
self.later(initlist())
return name
def nameof_dict(self, dic):
- name = self.find_global_name(dic)
- if name:
- return name
- return 'space.newdict([w("sorry", "not yet"])'
assert dic is not __builtins__
assert '__builtins__' not in dic, 'Seems to be the globals of %s' % (
dic.get('__name__', '?'),)
name = self.uniquename('g%ddict' % len(dic))
def initdict():
for k in dic:
- if type(k) is str:
- yield ('\tINITCHK(PyDict_SetItemString'
- '(%s, "%s", %s) >= 0)'%(
- name, k, self.nameof(dic[k])))
- else:
- yield ('\tINITCHK(PyDict_SetItem'
- '(%s, %s, %s) >= 0)'%(
- name, self.nameof(k), self.nameof(dic[k])))
- self.initcode.append('INITCHK(%s = PyDict_New())' % (name,))
+ yield ('space.setitem(%s, %s, %s)'%(
+ name, self.nameof(k), self.nameof(dic[k])))
+ self.initcode.append('m.%s = space.newdict([])' % (name,))
self.later(initdict())
return name
@@ -373,11 +630,9 @@
name = self.uniquename('gdescriptor_%s_%s' % (
md.__objclass__.__name__, md.__name__))
cls = self.nameof(md.__objclass__)
- self.initcode.append('INITCHK(PyType_Ready((PyTypeObject*) %s) >= 0)' %
- cls)
- self.initcode.append('INITCHK(%s = PyMapping_GetItemString('
- '((PyTypeObject*) %s)->tp_dict, "%s"))' %
- (name, cls, md.__name__))
+ # do I need to take the dict and then getitem???
+ self.initcode.append('m.%s = space.getattr(%s, %s)' %
+ (name, cls, self.nameof(md.__name__)))
return name
nameof_getset_descriptor = nameof_member_descriptor
nameof_method_descriptor = nameof_member_descriptor
@@ -392,103 +647,236 @@
return 'PySys_GetObject("stderr")'
raise Exception, 'Cannot translate an already-open file: %r' % (fil,)
- def gen_source(self):
+ def gen_source(self, fname, ftmpname=None):
+ self.fname = fname
+ self.ftmpname = ftmpname
+
+ # generate unordered source file, first.
+ # I prefer this over ordering everything in memory.
+ fname = self.fname
+ if self.ftmpname:
+ fname = self.ftmpname
+ f = file(fname, "w")
+ # generate ordered source file
+ try:
+ self.f = f
+ self.gen_source_temp()
+ finally:
+ f.close()
+
+ def copyfile(source, target):
+ file(target, "w").write(file(source).read())
+
+ def order_sections(fname):
+ sep = "\n##SECTION##\n"
+ txt = file(fname).read()
+ pieces = txt.split(sep)
+ prelude = pieces.pop(0)
+ postlude = pieces.pop()
+ dic = {}
+ while pieces:
+ func = pieces.pop()
+ head = pieces.pop()
+ key = makekey(head, len(pieces))
+ dic[key] = head + sep + func
+ lis = dic.items()
+ lis.sort()
+ lis = [prelude] + [func for head, func in lis] + [postlude]
+ txt = sep.join(lis)
+ file(fname, "w").write(txt)
+
+ def makekey(txt, uniqueno):
+ dic = {}
+ for line in txt.split("\n"):
+ ign, name, value = line.split(None, 2)
+ dic[name] = eval(value)
+ key = dic["filename"], dic["firstlineno"], uniqueno
+ return key
+
+ order_sections(fname)
+ if self.ftmpname:
+ copyfile(self.ftmpname, self.fname)
+
+ def gen_source_temp(self):
f = self.f
info = {
'modname': self.modname,
- 'entrypointname': self.translator.functions[0].__name__,
+ 'entrypointname': self.trans_funcname(
+ self.translator.functions[0].__name__),
'entrypoint': self.nameof(self.translator.functions[0]),
}
-
- # make sure
+ # header
+ print >> f, self.RPY_HEADER
# function implementations
while self.pendingfunctions:
- func = self.current_func = self.pendingfunctions.pop()
- self.adjust_namespace()
+ func = self.pendingfunctions.pop()
+ self.currentfunc = func
self.gen_rpyfunction(func)
# collect more of the latercode after each function
while self.latercode:
- #gen, self.debugstack = self.latercode.pop()
- gen = self.latercode.pop()
+ gen, self.debugstack = self.latercode.pop()
#self.initcode.extend(gen) -- eats TypeError! bad CPython!
for line in gen:
self.initcode.append(line)
self.debugstack = ()
- #self.gen_global_declarations()
- print >> f
+ self.gen_global_declarations()
+ # set the final splitter
+ print >> f, "##SECTION##"
# footer
- # maybe not needed
- return
- print >> f, self.C_INIT_HEADER % info
- if self.f2name is not None:
- print >> f, '#include "%s"' % self.f2name
- for codeline in self.initcode:
- print >> f, '\t' + codeline
- print >> f, self.C_INIT_FOOTER % info
+ print >> f, self.RPY_INIT_HEADER % info
+ for codelines in self.initcode:
+ for codeline in codelines.split("\n"):
+ print >> f, " %s" % codeline
+ print >> f, self.RPY_INIT_FOOTER % info
+ f.close()
+
+ def gen_global_declarations(self):
+ g = self.globaldecl
+ if g:
+ f = self.f
+ print >> f, '# global declaration%s' % ('s'*(len(g)>1))
+ for line in g:
+ print >> f, line
+ print >> f
+ del g[:]
+ g = self.globalobjects
+ for name in g:
+ pass # self.initcode.append('# REGISTER_GLOBAL(%s)' % (name,))
+ del g[:]
def gen_rpyfunction(self, func):
- local_names = {}
+ f = self.f
+ print >> f, "##SECTION##" # simple to split, afterwards
+ print >> f, ("## filename %r\n"
+ "## function %r\n"
+ "## firstlineno %d") % (
+ func.func_code.co_filename,
+ func.func_code.co_name,
+ func.func_code.co_firstlineno)
+ print >> f, "##SECTION##"
+ locals = {}
+ body = list(self.rpyfunction_body(func, locals))
+ name_of_defaults = [self.nameof(x, debug=('Default argument of', func))
+ for x in (func.func_defaults or ())]
+ self.gen_global_declarations()
+
+ # print header
+ cname = self.nameof(func)
+ assert cname.startswith('gfunc_')
+ f_name = 'f_' + cname[6:]
+
+ # collect all the local variables
+ graph = self.translator.getflowgraph(func)
+ localslst = []
+ def visit(node):
+ if isinstance(node, Block):
+ localslst.extend(node.getvariables())
+ traverse(visit, graph)
+ localnames = [self.expr(a, locals) for a in uniqueitems(localslst)]
+
+ # collect all the arguments
+ if func.func_code.co_flags & CO_VARARGS:
+ vararg = graph.getargs()[-1]
+ positional_args = graph.getargs()[:-1]
+ else:
+ vararg = None
+ positional_args = graph.getargs()
+ min_number_of_args = len(positional_args) - len(name_of_defaults)
+
+ fast_args = [self.expr(a, locals) for a in positional_args]
+ if vararg is not None:
+ fast_args.append(self.expr(vararg, locals))
+ fast_name = 'fast' + f_name
+
+ fast_set = dict(zip(fast_args, fast_args))
- def expr(v, wrapped = True):
- if isinstance(v, Variable):
- n = v.name
- if n.startswith("v") and n[1:].isdigit():
- ret = local_names.get(v.name)
- if not ret:
- if wrapped:
- local_names[v.name] = ret = "w_%d" % len(local_names)
- else:
- local_names[v.name] = ret = "v%d" % len(local_names)
- return ret
- return v.name
- elif isinstance(v, Constant):
- return self.nameof(v.value)
- else:
- #raise TypeError, "expr(%r)" % (v,)
- # XXX how do I resolve these?
- return "space.%s" % str(v)
-
- def arglist(args):
- res = [expr(arg) for arg in args]
- return ", ".join(res)
-
- def oper(op):
- print op.opname, op.args
- if op.opname == "simple_call":
- v = op.args[0]
- if isinstance(v, Constant) and self.find_global_name(v.value):
- fmt = "%s = %s(space, %s)"
- else:
- fmt = "%s = space.call(%s, space.newtuple([%s]))"
- return fmt % (expr(op.result), expr(op.args[0]), arglist(op.args[1:]))
- if op.opname in self.has_listarg:
- fmt = "%s = %s([%s])"
- else:
- fmt = "%s = %s(%s)"
- # specialcase is_true
- if op.opname == "is_true":
- return fmt % (expr(op.result, False), expr(op.opname), arglist(op.args))
- return fmt % (expr(op.result), expr(op.opname), arglist(op.args))
-
- def gen_link(link, linklocalvars=None):
- "Generate the code to jump across the given Link."
- linklocalvars = linklocalvars or {}
- left, right = [], []
- for a1, a2 in zip(link.args, link.target.inputargs):
- if a1 in linklocalvars:
- src = linklocalvars[a1]
- else:
- src = expr(a1)
- left.append(expr(a2))
- right.append(src)
- yield "%s = %s" % (", ".join(left), ", ".join(right))
- goto = blocknum[link.target]
- yield 'goto = %d' % goto
- if goto <= blocknum[block]:
- yield 'continue'
+ # create function declaration
+ name = func.__name__
+ argstr = ", ".join(fast_args)
+ fast_function_header = ('def %s(space, %s):'
+ % (fast_name, argstr))
+
+ print >> f, 'def %s(space, *args_w):' % (f_name,)
+ kwlist = ['"%s"' % name for name in
+ func.func_code.co_varnames[:func.func_code.co_argcount]]
+ print >> f, ' kwlist = [%s]' % (', '.join(kwlist),)
+
+ # argument unpacking
+ if vararg is not None:
+ varname = self.expr(vararg, locals)
+ lenargs = len(positional_args)
+ print >> f, ' %s = space.newtuple(list(args_w[%d:]))' % (
+ varname, lenargs)
+ print >> f, ' _args_w = args_w[:%d]' % (lenargs,)
+ else:
+ print >> f, ' _args_w = args_w'
+ varname = None
+
+ def tupstr(seq):
+ if len(seq) == 1:
+ fmt = '%s,'
+ else:
+ fmt = '%s'
+ return fmt % ', '.join(seq)
+
+ print >> f, ' defaults_w = (%s)' % tupstr(name_of_defaults)
+
+ theargs = [arg for arg in fast_args if arg != varname]
+ txt = ('from pypy.translator.genrpy import PyArg_ParseMini\n'
+ 'm.PyArg_ParseMini = PyArg_ParseMini\n'
+ 'from pypy.interpreter.error import OperationError\n'
+ 'm.OperationError = OperationError')
+ self.initcode.append(txt)
+ print >> f, ' funcname = "%s"' % func.__name__
+ if theargs:
+ txt = ' %s = PyArg_ParseMini(space, funcname, %d, %d, _args_w, defaults_w)'
+ print >>f, txt % (tupstr(theargs),
+ min_number_of_args, len(positional_args))
+ else:
+ txt = ' PyArg_ParseMini(space, funcname, %d, %d, _args_w, defaults_w)'
+ print >>f, txt % (min_number_of_args, len(positional_args))
+ print >> f, ' return %s(space, %s)' % (fast_name, ', '.join(fast_args))
+ print >> f
+
+ print >> f, fast_function_header
+
+ fast_locals = [arg for arg in localnames if arg not in fast_set]
+ if fast_locals:
+ print >> f
+ for line in self.large_initialize(fast_locals):
+ print >> f, " %s" % line
+ print >> f
+ # generate an incref for each input argument
+ # skipped
+
+ # print the body
+ for line in body:
+ print >> f, line
+ print >> f
+
+ # print the PyMethodDef
+ # skipped
+
+ if not self.translator.frozen:
+ # this is only to keep the RAM consumption under control
+ del self.translator.flowgraphs[func]
+ Variable.instances.clear()
+
+ def rpyfunction_body(self, func, localvars):
+ try:
+ graph = self.translator.getflowgraph(func)
+ except Exception, e:
+ print 20*"*", e
+ print func
+ raise
+ # not needed, we use tuple assignment!
+ # remove_direct_loops(graph)
+ checkgraph(graph)
+
+ allblocks = []
f = self.f
t = self.translator
@@ -496,65 +884,68 @@
graph = t.getflowgraph(func)
start = graph.startblock
- blocks = ordered_blocks(graph)
- nblocks = len(blocks)
+ allblocks = ordered_blocks(graph)
+ nblocks = len(allblocks)
blocknum = {}
- for block in blocks:
+ for block in allblocks:
blocknum[block] = len(blocknum)+1
- # create function declaration
- name = func.__name__ # change this
- args = [expr(var) for var in start.inputargs]
- argstr = ", ".join(args)
- print >> f, "def %s(space, %s):" % (name, argstr)
- print >> f, " w = space.wrap"
- print >> f, " goto = %d # startblock" % blocknum[start]
- print >> f, " while True:"
-
+ yield " goto = %d # startblock" % blocknum[start]
+ yield " while True:"
+
def render_block(block):
catch_exception = block.exitswitch == Constant(last_exception)
regular_op = len(block.operations) - catch_exception
# render all but maybe the last op
for op in block.operations[:regular_op]:
- yield "%s" % oper(op)
+ for line in self.oper(op, localvars).split("\n"):
+ yield "%s" % line
# render the last op if it is exception handled
for op in block.operations[regular_op:]:
yield "try:"
- yield " %s" % oper(op)
+ for line in self.oper(op, localvars).split("\n"):
+ yield " %s" % line
if len(block.exits) == 0:
if len(block.inputargs) == 2: # exc_cls, exc_value
# exceptional return block
- exc_cls = expr(block.inputargs[0])
- exc_val = expr(block.inputargs[1])
+ exc_cls = self.expr(block.inputargs[0], localvars)
+ exc_val = self.expr(block.inputargs[1], localvars)
yield "raise OperationError(%s, %s)" % (exc_cls, exc_val)
else:
# regular return block
- retval = expr(block.inputargs[0])
+ retval = self.expr(block.inputargs[0], localvars)
yield "return %s" % retval
return
elif block.exitswitch is None:
# single-exit block
assert len(block.exits) == 1
- for op in gen_link(block.exits[0]):
+ for op in self.gen_link(block.exits[0], localvars, blocknum, block):
yield "%s" % op
elif catch_exception:
# block catching the exceptions raised by its last operation
# we handle the non-exceptional case first
link = block.exits[0]
assert link.exitcase is None
- for op in gen_link(link):
+ for op in self.gen_link(link, localvars, blocknum, block):
yield " %s" % op
# we must catch the exception raised by the last operation,
# which goes to the last err%d_%d label written above.
+ # Since we only have OperationError, we need to select:
+ yield "except OperationError, e:"
+ q = "if"
for link in block.exits[1:]:
assert issubclass(link.exitcase, Exception)
- yield "except OperationError, e:"
- for op in gen_link(link, {
+ # Exeption classes come unwrapped in link.exitcase
+ yield " %s space.is_true(space.issubtype(e.w_type, %s)):" % (q,
+ self.nameof(link.exitcase))
+ q = "elif"
+ for op in self.gen_link(link, localvars, blocknum, block, {
Constant(last_exception): 'e.w_type',
Constant(last_exc_value): 'e.w_value'}):
- yield " %s" % op
+ yield " %s" % op
+ yield " else:raise # unhandled case, should not happen"
else:
# block ending in a switch on a value
exits = list(block.exits)
@@ -564,34 +955,101 @@
exits.reverse()
q = "if"
for link in exits[:-1]:
- yield "%s %s == %s:" % (q, expr(block.exitswitch),
+ yield "%s %s == %s:" % (q, self.expr(block.exitswitch,
+ localvars),
link.exitcase)
- for op in gen_link(link):
+ for op in self.gen_link(link, localvars, blocknum, block):
yield " %s" % op
q = "elif"
link = exits[-1]
yield "else:"
- yield " assert %s == %s" % (expr(block.exitswitch),
+ yield " assert %s == %s" % (self.expr(block.exitswitch,
+ localvars),
link.exitcase)
- for op in gen_link(exits[-1]):
+ for op in self.gen_link(exits[-1], localvars, blocknum, block):
yield " %s" % op
- for block in blocks:
+ for block in allblocks:
blockno = blocknum[block]
- print >> f
- print >> f, " if goto == %d:" % blockno
+ yield ""
+ yield " if goto == %d:" % blockno
for line in render_block(block):
- print >> f, " %s" % line
+ yield " %s" % line
+
+# ____________________________________________________________
+
+ RPY_HEADER = '#!/bin/env python\n# -*- coding: LATIN-1 -*-'
+
+ RPY_SEP = "#*************************************************************"
+
+ RPY_INIT_HEADER = RPY_SEP + '''
+
+def init%(modname)s(space):
+ """NOT_RPYTHON"""
+ class m: pass # fake module
+ m.__dict__ = globals()
+'''
+
+ RPY_INIT_FOOTER = '''
+# entry point: %(entrypointname)s, %(entrypoint)s)
+if __name__ == "__main__":
+ from pypy.objspace.std import StdObjSpace
+ space = StdObjSpace()
+ init%(modname)s(space)
+ print space.unwrap(space.call(
+ gfunc_%(entrypointname)s, space.newtuple([])))
+'''
+
+# a translation table suitable for str.translate() to remove
+# non-C characters from an identifier
+C_IDENTIFIER = ''.join([(('0' <= chr(i) <= '9' or
+ 'a' <= chr(i) <= 'z' or
+ 'A' <= chr(i) <= 'Z') and chr(i) or '_')
+ for i in range(256)])
+
+# temporary arg parsing
+# what about keywords? Gateway doesn't support it.
+def PyArg_ParseMini(space, name, minargs, maxargs, args_w, defaults_w):
+ err = None
+ if len(args_w) < minargs:
+ txt = "%s() takes at least %d argument%s (%d given)"
+ plural = ['s', ''][minargs == 1]
+ err = (name, minargs, plural, len(args_w))
+ if len(args_w) > maxargs:
+ plural = ['s', ''][maxargs == 1]
+ if minargs == maxargs:
+ if minargs == 0:
+ txt = '%s() takes no arguments (%d given)'
+ err = (name, len(args_w))
+ elif minargs == 1:
+ txt = '%s() takes exactly %d argument%s (%d given)'
+ err = (name, maxargs, plural, len(args_w))
+ else:
+ txt = '%s() takes at most %d argument%s (%d given)'
+ err = (name, maxargs, plural, len(args_w))
+ if err:
+ w_txt = space.wrap(txt)
+ w_tup = space.wrap(err)
+ w_txt = space.mod(w_txt, w_tup)
+ raise OperationError(space.w_TypeError, w_txt)
+
+ # finally, we create the result ;-)
+ res_w = args_w + defaults_w[len(args_w) - minargs:]
+ assert len(res_w) == maxargs
+ return res_w
+# _____________________________________________________________________
+
+## this should go into some test file
def somefunc(arg):
pass
def f(a,b):
- print "start"
+## print "start"
a = []
a.append(3)
for i in range(3):
- print i
+ pass#print i
if a > b:
try:
if b == 123:
@@ -605,12 +1063,20 @@
dummy = somefunc(23)
return 42
-def ff(a, b):
+class TestClass:pass
+
+def ff(a, b, c=3,*rest):
try:
- raise SystemError, 42
- return a+b
- finally:
- a = 7
+ try:
+ if rest:
+ raise SystemError, 42
+ return a+b
+ finally:
+ a = 7
+ if rest:
+ return len(rest),c
+ except TypeError:
+ print "eek"
glob = 100
def fff():
@@ -640,39 +1106,98 @@
#import md5
# how do I avoid the builtin module?
from pypy.appspace import md5
- digest = md5.new("hello")
+ digest = md5.new("hello").hexdigest()
+ return digest
def test_mod():
return app_mod__String_ANY("-%s-", ["hallo"])
-entry_point = (f, ff, fff, app_str_decode__String_ANY_ANY, test_mod, test_md5) [-2]
+def test_join():
+ return " ".join(["hi", "there"])
+
+# cannot nest local classes, yet
+# this appears to be a problem in flow space.
+class AnIterClass(object):
+ def __init__(self):
+ self.lis = [c for c in "test"]
+ def next(self):
+ if self.lis:
+ return self.lis.pop()
+ raise StopIteration
+ def __iter__(self):
+ return self
+
+def test_iter():
+ res = []
+ for i in "hallo":
+ res.append(i)
+ for i in AnIterClass():
+ res.append(i)
+ return res
+
+def test_strutil():
+ from pypy.objspace.std import strutil
+ return (strutil.string_to_int("42"),
+ strutil.string_to_long("12345678901234567890"))
+
+def test_struct():
+ from pypy.appspace import struct
+ import struct as stru
+ res1 = stru.pack('f',1.23), struct.pack('f',1.23)
+ res2 = struct.unpack('f', struct.pack('f',1.23))
+ return res1, res2
+
+def all_entries():
+ res = [func() for func in entry_points[:-1]]
+ return res
+
+entry_points = (lambda: f(2, 3),
+ lambda: ff(2, 3, 5),
+ fff,
+ lambda: app_str_decode__String_ANY_ANY("hugo"),
+ test_mod,
+ test_md5,
+ test_join,
+ test_iter,
+ test_strutil,
+ test_struct,
+ all_entries)
+entry_point = entry_points[-2]
+
+if __name__ == "__main__":
+ import os, sys
+ from pypy.interpreter import autopath
+ srcdir = os.path.dirname(autopath.pypydir)
+ appdir = os.path.join(autopath.pypydir, 'appspace')
+
+ if appdir not in sys.path:
+ sys.path.insert(0, appdir)
-import os, sys
-from pypy.interpreter import autopath
-srcdir = os.path.dirname(autopath.pypydir)
-appdir = os.path.join(autopath.pypydir, 'appspace')
-
-try:
- hold = sys.path[:]
- sys.path.insert(0, appdir)
t = Translator(entry_point, verbose=False, simplifying=True)
- if 0:
- gen = GenRpy(sys.stdout, t)
- else:
- fil= file("d:/tmp/look.py", "w")
- gen = GenRpy(fil, t)
- print >> fil, \
-"""
-from pypy.objspace.std import StdObjSpace
-space = StdObjSpace()
-space.simple_call = space.call
-test_mod(space)
-"""
- fil.close()
-finally:
- sys.path[:] = hold
-#t.simplify()
-#t.view()
-# debugging
-graph = t.getflowgraph()
-ab = ordered_blocks(graph) # use ctrl-b in PyWin with ab
+ gen = GenRpy(t)
+ gen.use_fast_call = True
+ import pypy.appspace.generated as tmp
+ pth = os.path.dirname(tmp.__file__)
+ ftmpname = "d:/tmp/look.py"
+ fname = os.path.join(pth, gen.modname+".py")
+ gen.gen_source(fname, ftmpname)
+
+ #t.simplify()
+ #t.view()
+ # debugging
+ graph = t.getflowgraph()
+ ab = ordered_blocks(graph) # use ctrl-b in PyWin with ab
+
+def crazy_test():
+ """ this thingy is generating the whole interpreter in itself"""
+ # but doesn't work, my goto's give a problem for flow space
+ dic = {"__builtins__": __builtins__, "__name__": "__main__"}
+ execfile("d:/tmp/look.py", dic)
+
+ def test():
+ f_ff(space, 2, 3)
+ test = type(test)(test.func_code, dic)
+
+ t = Translator(test, verbose=False, simplifying=True)
+ gen = GenRpy(t)
+ gen.gen_source("d:/tmp/look2.py")
Copied: pypy/branch/src-pytest/pypy/translator/java/test/test_javatrans.py (from r8225, pypy/trunk/src/pypy/translator/java/test/test_javatrans.py)
==============================================================================
--- pypy/trunk/src/pypy/translator/java/test/test_javatrans.py (original)
+++ pypy/branch/src-pytest/pypy/translator/java/test/test_javatrans.py Wed Jan 12 15:31:13 2005
@@ -1,16 +1,14 @@
import autopath, os
from py.process import cmdexec
-from pypy.tool import testit
from pypy.tool.udir import udir
from pypy.translator.java.genjava import GenJava
from pypy.translator.test import snippet
from pypy.translator.translator import Translator
-class NoTypeCGenTestCase(testit.IntTestCase):
+class TestNoTypeCGenTestCase:
- def setUp(self):
- self.space = testit.objspace('flow')
+ objspacename = 'flow'
def build_jfunc(self, func):
try: func = func.im_func
@@ -27,7 +25,7 @@
try:
os.chdir(str(self.jdir))
cmdexec('javac *.java')
- self.assertEquals(cmdexec('java test').strip(), 'OK')
+ assert cmdexec('java test').strip() == 'OK'
finally:
os.chdir(cwd)
@@ -48,7 +46,3 @@
def test_sieve_of_eratosthenes(self):
self.build_jfunc(snippet.sieve_of_eratosthenes)
self.check([], 1028)
-
-
-if __name__ == '__main__':
- testit.main()
Modified: pypy/branch/src-pytest/pypy/translator/test/test_ctrans.py
==============================================================================
--- pypy/branch/src-pytest/pypy/translator/test/test_ctrans.py (original)
+++ pypy/branch/src-pytest/pypy/translator/test/test_ctrans.py Wed Jan 12 15:31:13 2005
@@ -150,7 +150,7 @@
raises(TypeError, call_with_star, [4,7,12,63])
raises(TypeError, call_with_star, 521)
- def XXX_test_call_with_keyword(self):
+ def test_call_with_keyword(self):
call_with_keyword = self.build_cfunc(snippet.call_with_keyword)
assert call_with_keyword(100) == 82
Modified: pypy/branch/src-pytest/pypy/translator/tool/buildpyxmodule.py
==============================================================================
--- pypy/branch/src-pytest/pypy/translator/tool/buildpyxmodule.py (original)
+++ pypy/branch/src-pytest/pypy/translator/tool/buildpyxmodule.py Wed Jan 12 15:31:13 2005
@@ -53,7 +53,7 @@
lastdir = path.local()
os.chdir(str(dirpath))
try:
- modname = cfile.purebasename
+ modname = cfile.purebasename
if debug: print "modname", modname
c = stdoutcapture.Capture(mixed_out_err = True)
try:
More information about the Pypy-commit
mailing list