[pypy-svn] r7535 - in pypy/trunk/src/pypy: interpreter interpreter/test objspace/flow objspace/std tool translator translator/test
arigo at codespeak.net
arigo at codespeak.net
Sun Nov 21 20:13:09 CET 2004
Author: arigo
Date: Sun Nov 21 20:13:08 2004
New Revision: 7535
Modified:
pypy/trunk/src/pypy/interpreter/eval.py
pypy/trunk/src/pypy/interpreter/executioncontext.py
pypy/trunk/src/pypy/interpreter/generator.py
pypy/trunk/src/pypy/interpreter/miscutils.py
pypy/trunk/src/pypy/interpreter/pyframe.py
pypy/trunk/src/pypy/interpreter/pyopcode.py
pypy/trunk/src/pypy/interpreter/test/test_interpreter.py
pypy/trunk/src/pypy/interpreter/typedef.py
pypy/trunk/src/pypy/objspace/flow/flowcontext.py
pypy/trunk/src/pypy/objspace/flow/framestate.py
pypy/trunk/src/pypy/objspace/flow/objspace.py
pypy/trunk/src/pypy/objspace/flow/specialcase.py
pypy/trunk/src/pypy/objspace/std/fake.py
pypy/trunk/src/pypy/objspace/std/typeobject.py
pypy/trunk/src/pypy/tool/cache.py
pypy/trunk/src/pypy/translator/genc.h
pypy/trunk/src/pypy/translator/genc.py
pypy/trunk/src/pypy/translator/test/snippet.py
pypy/trunk/src/pypy/translator/test/test_ctrans.py
pypy/trunk/src/pypy/translator/translator.py
Log:
Progress on translate_pypy -no-a. Now it's starting to complain on real
bugs on our RPython code, like typos in never-tested branches or locals
that could be undefined in some rare cases.
- a typo in EXTENDED_ARG. In other words it never worked.
Added a test (not so easy...).
- a few extra NOT_RPYTHON annotations, an extra Cache() usage.
- bare raise statements (to re-raise exceptions) now supported by the flow
object space. Required minor changes in the methods of the
pypy.interpreter.eval.Frame class.
- in the flow graphs, "raise Class" doesn't try to build a Class()
instance as the exception value any more; it uses None. (It doesn't try
to do any normalization at all.)
- always check the length of the iterable in
FlowObjSpace.unpackiterable().
- NameErroring typo in untested code in fake.py.
- typeobject.compute_C3_mro() shows an exemple of code that the flow
object space complains about: 'candidate' might be undefined. We
now it cannot be; let's use a return statement to help the flow
objspace.
- a few memory-saving hacks in genc.py allow it to consume a nearly
constant amount of heap, instead of growing fast.
- OP_LEN in genc.h.
- (hopefully temporary) got tired of finding where to freeze the caches,
and did it in Cache.__hash__().
Modified: pypy/trunk/src/pypy/interpreter/eval.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/eval.py (original)
+++ pypy/trunk/src/pypy/interpreter/eval.py Sun Nov 21 20:13:08 2004
@@ -70,12 +70,7 @@
def run(self):
"Run the frame."
executioncontext = self.space.getexecutioncontext()
- previous = executioncontext.enter(self)
- try:
- result = self.eval(executioncontext)
- finally:
- executioncontext.leave(previous)
- return result
+ return executioncontext.run_frame(self)
def eval(self, executioncontext):
"Abstract method to override."
Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/executioncontext.py (original)
+++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sun Nov 21 20:13:08 2004
@@ -9,17 +9,18 @@
self.space = space
self.framestack = Stack()
- def enter(self, frame):
+ def run_frame(self, frame):
locals = getthreadlocals()
- self.framestack.push(frame)
previous_ec = locals.executioncontext
locals.executioncontext = self
- return previous_ec
-
- def leave(self, previous_ec):
- locals = getthreadlocals()
- locals.executioncontext = previous_ec
- self.framestack.pop()
+ self.framestack.push(frame)
+ try:
+ w_result = frame.eval(self)
+ finally:
+ self.framestack.pop()
+ locals = getthreadlocals()
+ locals.executioncontext = previous_ec
+ return w_result
def get_w_builtins(self):
if self.framestack.empty():
Modified: pypy/trunk/src/pypy/interpreter/generator.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/generator.py (original)
+++ pypy/trunk/src/pypy/interpreter/generator.py Sun Nov 21 20:13:08 2004
@@ -47,16 +47,17 @@
return self.space.wrap(self)
def descr_next(self):
- space = self.frame.space
+ space = self.space
if self.running:
raise OperationError(space.w_ValueError,
space.wrap('generator already executing'))
if self.frame.exhausted:
raise OperationError(space.w_StopIteration, space.w_None)
+ executioncontext = space.getexecutioncontext()
self.running = True
try:
try:
- return Frame.run(self.frame)
+ return executioncontext.run_frame(self.frame)
except OperationError, e:
if e.match(self.space, self.space.w_StopIteration):
raise OperationError(space.w_StopIteration, space.w_None)
Modified: pypy/trunk/src/pypy/interpreter/miscutils.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/miscutils.py (original)
+++ pypy/trunk/src/pypy/interpreter/miscutils.py Sun Nov 21 20:13:08 2004
@@ -40,8 +40,8 @@
class InitializedClass(type):
- """A meta-class that allows a class to initialize itself (or its
- subclasses) by calling __initclass__() as a class method."""
+ """NOT_RPYTHON. A meta-class that allows a class to initialize itself (or
+ its subclasses) by calling __initclass__() as a class method."""
def __init__(self, name, bases, dict):
super(InitializedClass, self).__init__(name, bases, dict)
for basecls in self.__mro__:
@@ -51,8 +51,9 @@
class RwDictProxy(object):
- """A dict-like class standing for 'cls.__dict__', to work around
- the fact that the latter is a read-only proxy for new-style classes."""
+ """NOT_RPYTHON. A dict-like class standing for 'cls.__dict__', to work
+ around the fact that the latter is a read-only proxy for new-style
+ classes."""
def __init__(self, cls):
self.cls = cls
Modified: pypy/trunk/src/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyframe.py (original)
+++ pypy/trunk/src/pypy/interpreter/pyframe.py Sun Nov 21 20:13:08 2004
@@ -41,9 +41,9 @@
"Interpreter main loop!"
try:
while True:
+ executioncontext.bytecode_trace(self)
+ last_instr = self.next_instr
try:
- executioncontext.bytecode_trace(self)
- last_instr = self.next_instr
try:
# fetch and dispatch the next opcode
# dispatch() is abstract, see pyopcode.
Modified: pypy/trunk/src/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyopcode.py (original)
+++ pypy/trunk/src/pypy/interpreter/pyopcode.py Sun Nov 21 20:13:08 2004
@@ -754,7 +754,7 @@
def EXTENDED_ARG(f, oparg):
opcode = f.nextop()
oparg = oparg<<16 | f.nextarg()
- fn = self.dispatch_table[opcode]
+ fn = f.dispatch_table[opcode]
if not fn.has_arg:
raise pyframe.BytecodeCorruption
fn(f, oparg)
Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original)
+++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Sun Nov 21 20:13:08 2004
@@ -160,6 +160,26 @@
''')
self.codetest(code, 'f', [])
+ def test_extended_arg(self):
+ longexpr = 'x = x or ' + '-x' * 2500
+ code = '''
+def f(x):
+ %s
+ %s
+ %s
+ %s
+ %s
+ %s
+ %s
+ %s
+ %s
+ %s
+ while x:
+ x -= 1 # EXTENDED_ARG is for the JUMP_ABSOLUTE at the end of the loop
+ return x
+''' % ((longexpr,)*10)
+ self.assertEquals(self.codetest(code, 'f', [3]), 0)
+
class AppTestInterpreter(testit.AppTestCase):
def test_trivial(self):
Modified: pypy/trunk/src/pypy/interpreter/typedef.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/typedef.py (original)
+++ pypy/trunk/src/pypy/interpreter/typedef.py Sun Nov 21 20:13:08 2004
@@ -5,60 +5,63 @@
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError
+from pypy.tool.cache import Cache
+import new
class TypeDef:
def __init__(self, __name, __base=None, **rawdict):
+ "NOT_RPYTHON: initialization-time only"
self.name = __name
self.base = __base
self.hasdict = '__dict__' in rawdict or (__base and __base.hasdict)
self.rawdict = rawdict
-unique_interplevel_subclass_cache = {}
+unique_interplevel_subclass_cache = Cache()
def get_unique_interplevel_subclass(cls):
- try:
- return unique_interplevel_subclass_cache[cls]
- except KeyError:
- typedef = cls.typedef
- name = 'User' + cls.__name__
- body = {}
-
- class User_InsertNameHere(object):
-
- def getclass(self, space):
- return self.w__class__
-
- def setclass(self, w_subtype):
- # XXX sanity checks here
+ return unique_interplevel_subclass_cache.getorbuild(cls, _buildusercls, None)
+
+def _buildusercls(cls, ignored):
+ "NOT_RPYTHON: initialization-time only"
+ typedef = cls.typedef
+ name = 'User' + cls.__name__
+ body = {}
+
+ class User_InsertNameHere(object):
+
+ def getclass(self, space):
+ return self.w__class__
+
+ def setclass(self, w_subtype):
+ # XXX sanity checks here
+ self.w__class__ = w_subtype
+
+ if typedef.hasdict:
+ def user_setup(self, space, w_subtype):
+ self.space = space
self.w__class__ = w_subtype
-
- if typedef.hasdict:
- def user_setup(self, space, w_subtype):
- self.space = space
- self.w__class__ = w_subtype
-
- else:
- def getdict(self):
- return self.w__dict__
-
- def setdict(self, w_dict):
- space = self.space
- if not space.is_true(space.isinstance(w_dict, space.w_dict)):
- raise OperationError(space.w_TypeError,
- space.wrap("setting dictionary to a non-dict"))
- self.w__dict__ = w_dict
-
- def user_setup(self, space, w_subtype):
- self.space = space
- self.w__class__ = w_subtype
- self.w__dict__ = space.newdict([])
-
- body = dict([(key, value)
- for key, value in User_InsertNameHere.__dict__.items()
- if not key.startswith('_')])
- subcls = type(name, (cls,), body)
- unique_interplevel_subclass_cache[cls] = subcls
- return subcls
+
+ else:
+ def getdict(self):
+ return self.w__dict__
+
+ def setdict(self, w_dict):
+ space = self.space
+ if not space.is_true(space.isinstance(w_dict, space.w_dict)):
+ raise OperationError(space.w_TypeError,
+ space.wrap("setting dictionary to a non-dict"))
+ self.w__dict__ = w_dict
+
+ def user_setup(self, space, w_subtype):
+ self.space = space
+ self.w__class__ = w_subtype
+ self.w__dict__ = space.newdict([])
+
+ body = dict([(key, value)
+ for key, value in User_InsertNameHere.__dict__.items()
+ if not key.startswith('_')])
+ subcls = type(name, (cls,), body)
+ return subcls
def instantiate(cls):
"Create an empty instance of 'cls'."
@@ -69,6 +72,7 @@
class GetSetProperty(Wrappable):
def __init__(self, fget, fset=None, fdel=None, doc=None):
+ "NOT_RPYTHON: initialization-time only"
fget = getattr(fget, 'im_func', fget)
fset = getattr(fset, 'im_func', fset)
fdel = getattr(fdel, 'im_func', fdel)
@@ -106,12 +110,14 @@
)
def attrproperty(name):
+ "NOT_RPYTHON: initialization-time only"
def fget(space, w_obj):
obj = space.unwrap_builtin(w_obj)
return space.wrap(getattr(obj, name))
return GetSetProperty(fget)
def attrproperty_w(name):
+ "NOT_RPYTHON: initialization-time only"
def fget(space, w_obj):
obj = space.unwrap_builtin(w_obj)
w_value = getattr(obj, name)
Modified: pypy/trunk/src/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/flowcontext.py (original)
+++ pypy/trunk/src/pypy/objspace/flow/flowcontext.py Sun Nov 21 20:13:08 2004
@@ -205,7 +205,7 @@
except ExitFrame:
continue # restarting a dead SpamBlock
try:
- w_result = frame.eval(self)
+ w_result = self.run_frame(frame)
except OperationError, e:
link = Link([e.w_type, e.w_value], self.graph.exceptblock)
self.crnt_block.closeblock(link)
Modified: pypy/trunk/src/pypy/objspace/flow/framestate.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/framestate.py (original)
+++ pypy/trunk/src/pypy/objspace/flow/framestate.py Sun Nov 21 20:13:08 2004
@@ -1,4 +1,5 @@
from pypy.interpreter.pyframe import PyFrame, ControlFlowException
+from pypy.interpreter.error import OperationError
from pypy.objspace.flow.model import *
class FrameState:
@@ -7,11 +8,16 @@
def __init__(self, state):
if isinstance(state, PyFrame):
data = state.getfastscope() + state.valuestack.items
+ if state.last_exception is None:
+ data.append(Constant(None))
+ data.append(Constant(None))
+ else:
+ data.append(state.last_exception.w_type)
+ data.append(state.last_exception.w_value)
recursively_flatten(state.space, data)
self.mergeable = data
self.nonmergeable = (
state.blockstack.items[:],
- state.last_exception,
state.next_instr,
state.w_locals,
)
@@ -30,10 +36,14 @@
data = self.mergeable[:]
recursively_unflatten(frame.space, data)
frame.setfastscope(data[:fastlocals])
- frame.valuestack.items[:] = data[fastlocals:]
+ frame.valuestack.items[:] = data[fastlocals:-2]
+ if data[-2] == Constant(None):
+ assert data[-1] == Constant(None)
+ frame.last_exception = None
+ else:
+ frame.last_exception = OperationError(data[-2], data[-1])
(
frame.blockstack.items[:],
- frame.last_exception,
frame.next_instr,
frame.w_locals,
) = self.nonmergeable
Modified: pypy/trunk/src/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/objspace.py (original)
+++ pypy/trunk/src/pypy/objspace/flow/objspace.py Sun Nov 21 20:13:08 2004
@@ -171,7 +171,11 @@
items.append(w_item)
i += 1
return items
- elif expected_length is not None:
+ elif expected_length is not None:
+ w_len = self.len(w_iterable)
+ w_correct = self.eq(w_len, self.wrap(expected_length))
+ if not self.is_true(w_correct):
+ raise OperationError(self.w_ValueError, self.w_None)
return [self.do_operation('getitem', w_iterable, self.wrap(i))
for i in range(expected_length)]
# XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK
Modified: pypy/trunk/src/pypy/objspace/flow/specialcase.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/specialcase.py (original)
+++ pypy/trunk/src/pypy/objspace/flow/specialcase.py Sun Nov 21 20:13:08 2004
@@ -21,7 +21,7 @@
* raise Class
- with a constant Class, it is easy to recognize.
- The associated value is Class().
+ But we don't normalize: the associated value is None.
* raise Class(...)
- when the class is instantiated in-place, we can figure that out
@@ -42,8 +42,7 @@
etype = getconstclass(space, w_arg1)
if etype is not None:
# raise Class
- w_arg2 = space.do_operation('simple_call', w_arg1)
- return (w_arg1, w_arg2)
+ return (w_arg1, space.w_None)
# raise Class(..)? We need a hack to figure out of which class it is.
# Normally, Instance should have been created by the previous operation
# which should be a simple_call(<Class>, ...).
Modified: pypy/trunk/src/pypy/objspace/std/fake.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/fake.py (original)
+++ pypy/trunk/src/pypy/objspace/std/fake.py Sun Nov 21 20:13:08 2004
@@ -16,10 +16,9 @@
# real-to-wrapped exceptions
def wrap_exception(space):
- "NOT_RPYTHON" # XXX this needs to end up in the translated code somehow!
exc, value, tb = sys.exc_info()
if exc is OperationError:
- raise exc, value, tb # just re-raise it
+ raise exc, value #, tb # just re-raise it (tb ignored: not RPython)
name = exc.__name__
if hasattr(space, 'w_' + name):
w_exc = getattr(space, 'w_' + name)
@@ -31,7 +30,7 @@
else:
w_exc = space.wrap(exc)
w_value = space.wrap(value)
- raise OperationError, OperationError(w_exc, w_value), tb
+ raise OperationError, OperationError(w_exc, w_value) #, tb not RPython
def fake_type(cpy_type):
assert type(cpy_type) is type
@@ -96,7 +95,7 @@
unwrappedargs = self.space.unwrap(w_args)
unwrappedkwds = self.space.unwrap(w_kwds)
except UnwrapError, e:
- raise UnwrapError('calling %s: %s' % (cpy_type, e))
+ raise UnwrapError('calling %s: %s' % (fn, e))
try:
result = apply(fn, unwrappedargs, unwrappedkwds)
except:
Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/typeobject.py (original)
+++ pypy/trunk/src/pypy/objspace/std/typeobject.py Sun Nov 21 20:13:08 2004
@@ -174,7 +174,7 @@
if mro_blockinglist(candidate, orderlists) is None:
break # good candidate
else:
- mro_error(orderlists) # no candidate found
+ return mro_error(orderlists) # no candidate found
assert candidate not in order
order.append(candidate)
for i in range(len(orderlists)-1, -1, -1):
Modified: pypy/trunk/src/pypy/tool/cache.py
==============================================================================
--- pypy/trunk/src/pypy/tool/cache.py (original)
+++ pypy/trunk/src/pypy/tool/cache.py Sun Nov 21 20:13:08 2004
@@ -9,7 +9,8 @@
def __hash__(self):
if not self.frozen:
- raise TypeError, "cannot get hash of un-frozen cache"
+ #raise TypeError, "cannot get hash of un-frozen cache"
+ self.freeze()
return id(self)
def clear(self):
Modified: pypy/trunk/src/pypy/translator/genc.h
==============================================================================
--- pypy/trunk/src/pypy/translator/genc.h (original)
+++ pypy/trunk/src/pypy/translator/genc.h Sun Nov 21 20:13:08 2004
@@ -22,11 +22,11 @@
#endif
#define op_bool(r,err,what) { \
- int retval = what; \
- if (retval < 0) { \
+ int _retval = what; \
+ if (_retval < 0) { \
FAIL(err) \
} \
- r = PyBool_FromLong(retval); \
+ r = PyBool_FromLong(_retval); \
}
#define op_richcmp(x,y,r,err,dir) \
@@ -42,6 +42,13 @@
#define OP_IS_TRUE(x,r,err) op_bool(r,err,PyObject_IsTrue(x))
+#define OP_LEN(x,r,err) { \
+ int _retval = PyObject_Size(x); \
+ if (_retval < 0) { \
+ FAIL(err) \
+ } \
+ r = PyInt_FromLong(_retval); \
+ }
#define OP_NEG(x,r,err) if (!(r=PyNumber_Negative(x))) FAIL(err)
#define OP_POS(x,r,err) if (!(r=PyNumber_Positive(x))) FAIL(err)
#define OP_INVERT(x,r,err) if (!(r=PyNumber_Invert(x))) FAIL(err)
Modified: pypy/trunk/src/pypy/translator/genc.py
==============================================================================
--- pypy/trunk/src/pypy/translator/genc.py (original)
+++ pypy/trunk/src/pypy/translator/genc.py Sun Nov 21 20:13:08 2004
@@ -39,8 +39,10 @@
class GenC:
MODNAMES = {}
- def __init__(self, f, translator, modname=None):
+ def __init__(self, f, translator, modname=None, f2=None, f2name=None):
self.f = f
+ self.f2 = f2
+ self.f2name = f2name
self.translator = translator
self.modname = (modname or
uniquemodulename(translator.functions[0].__name__))
@@ -69,7 +71,8 @@
else:
stackentry = obj
self.debugstack = (self.debugstack, stackentry)
- if type(obj).__module__ != '__builtin__':
+ if (type(obj).__module__ != '__builtin__' and
+ not isinstance(obj, type)): # skip user-defined metaclasses
# assume it's a user defined thingy
name = self.nameof_instance(obj)
else:
@@ -151,10 +154,10 @@
return name
def nameof_str(self, value):
- chrs = [c for c in value if ('a' <= c <='z' or
- 'A' <= c <='Z' or
- '0' <= c <='9' or
- '_' == c )]
+ chrs = [c for c in value[:32] if ('a' <= c <='z' or
+ 'A' <= c <='Z' or
+ '0' <= c <='9' or
+ '_' == c )]
name = self.uniquename('gstr_' + ''.join(chrs))
if [c for c in value if not (' '<=c<='~')]:
# non-printable string
@@ -179,7 +182,8 @@
self.initcode.append('\tPyCFunction_GET_SELF(%s) = %s;' % (name, name))
return name
- def nameof_function(self, func):
+ def nameof_function(self, func, progress=['-\x08', '\\\x08',
+ '|\x08', '/\x08']):
printable_name = '(%s:%d) %s' % (
func.func_globals.get('__name__', '?'),
func.func_code.co_firstlineno,
@@ -193,7 +197,9 @@
func.func_doc.lstrip().startswith('NOT_RPYTHON')):
print "skipped", printable_name
return self.skipped_function(func)
- #print "nameof", printable_name
+ p = progress.pop(0)
+ sys.stderr.write(p)
+ progress.append(p)
name = self.uniquename('gfunc_' + func.__name__)
self.initcode.append('INITCHK(%s = PyCFunction_New('
'&ml_%s, NULL))' % (name, name))
@@ -313,7 +319,7 @@
for key, value in content:
if key.startswith('__'):
if key in ['__module__', '__doc__', '__dict__',
- '__weakref__', '__repr__']:
+ '__weakref__', '__repr__', '__metaclass__']:
continue
# XXX some __NAMES__ are important... nicer solution sought
#raise Exception, "unexpected name %r in class %s"%(key, cls)
@@ -350,6 +356,7 @@
dict: '&PyDict_Type',
str: '&PyString_Type',
float: '&PyFloat_Type',
+ type(Exception()): '&PyInstance_Type',
type: '&PyType_Type',
complex:'&PyComplex_Type',
unicode:'&PyUnicode_Type',
@@ -458,7 +465,7 @@
# function implementations
while self.pendingfunctions:
- func = self.pendingfunctions.pop(0)
+ func = self.pendingfunctions.pop()
self.gen_cfunction(func)
# collect more of the latercode after each function
while self.latercode:
@@ -471,10 +478,10 @@
# footer
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
- for name in self.globalobjects:
- print >> f, '\t' + 'REGISTER_GLOBAL(%s)' % (name,)
print >> f, self.C_INIT_FOOTER % info
def gen_global_declarations(self):
@@ -486,6 +493,14 @@
print >> f, line
print >> f
del g[:]
+ g = self.globalobjects
+ for name in g:
+ self.initcode.append('REGISTER_GLOBAL(%s)' % (name,))
+ del g[:]
+ if self.f2 is not None:
+ for line in self.initcode:
+ print >> self.f2, line
+ del self.initcode[:]
def gen_cfunction(self, func):
## print 'gen_cfunction (%s:%d) %s' % (
@@ -584,6 +599,11 @@
name, func.__name__, f_name)
print >> f
+ if not self.translator.frozen:
+ # this is only to keep the RAM consumption under control
+ del self.translator.flowgraphs[func]
+ Variable.instances.clear()
+
def cfunction_body(self, func):
graph = self.translator.getflowgraph(func)
remove_direct_loops(graph)
@@ -653,7 +673,7 @@
# exceptional return block
exc_cls = expr(block.inputargs[0])
exc_value = expr(block.inputargs[1])
- yield 'PyErr_SetObject(%s, %s);' % (exc_cls, retval)
+ yield 'PyErr_Restore(%s, %s, NULL);' % (exc_cls, exc_value)
yield 'FUNCTION_RETURN(NULL)'
else:
# regular return block
Modified: pypy/trunk/src/pypy/translator/test/snippet.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/snippet.py (original)
+++ pypy/trunk/src/pypy/translator/test/snippet.py Sun Nov 21 20:13:08 2004
@@ -234,6 +234,19 @@
x = 8
return x
+def finally2(o, k):
+ try:
+ o[k] += 1
+ finally:
+ o[-1] = 'done'
+
+def bare_raise(o, ignore):
+ try:
+ return o[5]
+ except:
+ if not ignore:
+ raise
+
def factorial(n=int):
if n <= 1:
return 1
Modified: pypy/trunk/src/pypy/translator/test/test_ctrans.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/test_ctrans.py (original)
+++ pypy/trunk/src/pypy/translator/test/test_ctrans.py Sun Nov 21 20:13:08 2004
@@ -140,6 +140,29 @@
self.assertEquals(call_default_and_star_args(42),
(111+42+3+0, -1000-2000-3000+2))
+ def test_finallys(self):
+ finallys = self.build_cfunc(snippet.finallys)
+ self.assertEquals(finallys(['hello']), 8)
+ self.assertEquals(finallys('X'), 8)
+ self.assertEquals(finallys([]), 6)
+ self.assertEquals(finallys('XY'), 6)
+
+ def test_finally2(self):
+ finally2 = self.build_cfunc(snippet.finally2)
+ lst = range(10)
+ finally2(lst, 5)
+ self.assertEquals(lst, [0,1,2,3,4, 6, 6,7,8, 'done'])
+ dic = {}
+ self.assertRaises(KeyError, finally2, dic, "won't find this key")
+ self.assertEquals(dic, {-1: 'done'})
+
+ def test_bare_raise(self):
+ bare_raise = self.build_cfunc(snippet.bare_raise)
+ self.assertEquals(bare_raise(range(0, 100, 10), False), 50)
+ self.assertEquals(bare_raise(range(0, 100, 10), True), 50)
+ self.assertRaises(IndexError, bare_raise, range(0, 30, 10), False)
+ self.assertEquals(bare_raise(range(0, 30, 10), True), None)
+
class TypedTestCase(testit.IntTestCase):
def getcompiled(self, func):
Modified: pypy/trunk/src/pypy/translator/translator.py
==============================================================================
--- pypy/trunk/src/pypy/translator/translator.py (original)
+++ pypy/trunk/src/pypy/translator/translator.py Sun Nov 21 20:13:08 2004
@@ -212,9 +212,7 @@
return g.globaldeclarations()
def compile(self):
- """Returns compiled function.
-
- Currently function is only compiled using Pyrex.
+ """Returns compiled function, compiled using Pyrex.
"""
from pypy.tool.udir import udir
name = self.entrypoint.func_name
@@ -229,7 +227,9 @@
name = uniquemodulename(self.entrypoint.func_name)
cfile = udir.join('%s.c' % name)
f = cfile.open('w')
- GenC(f, self, name)
+ f2 = udir.join('%s-init.h' % name).open('w')
+ GenC(f, self, name, f2=f2, f2name='%s-init.h' % name)
+ f2.close()
f.close()
if not really_compile:
return cfile
More information about the Pypy-commit
mailing list