[pypy-svn] r25725 - in pypy/dist/pypy/translator/cli: . test
antocuni at codespeak.net
antocuni at codespeak.net
Wed Apr 12 18:29:44 CEST 2006
Author: antocuni
Date: Wed Apr 12 18:29:32 2006
New Revision: 25725
Modified:
pypy/dist/pypy/translator/cli/cts.py
pypy/dist/pypy/translator/cli/database.py
pypy/dist/pypy/translator/cli/function.py
pypy/dist/pypy/translator/cli/metavm.py
pypy/dist/pypy/translator/cli/opcodes.py
pypy/dist/pypy/translator/cli/test/compile.py
Log:
Refactored exception handling: the first try was to translate Python
exception to CLI exceptions, but this would have caused some trobules
because the two inheritance hierarchies don't overlap.
Now Python exceptions has its own CLI hierarchy, generated in exactly
the same way that is for other classes. This means that we can no
longer rely on CLI '.ovf' opcodes that raises OverflowException on
error, because Python's OverflowError doesn't map to CLI's
OverfloweException. For now the tricky and inefficient solution is to
explicitly catch OverflowException and throw a fresh OverflowError
instead.
Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py (original)
+++ pypy/dist/pypy/translator/cli/cts.py Wed Apr 12 18:29:32 2006
@@ -49,16 +49,21 @@
def __init__(self, db):
self.db = db
- def lltype_to_cts(self, t):
+ def __class(self, result, include_class):
+ if include_class:
+ return 'class ' + result
+ else:
+ return result
+
+ def lltype_to_cts(self, t, include_class=True):
if isinstance(t, Instance):
- name = t._name
self.db.pending_class(t)
- return 'class %s' % name
+ return self.__class(t._name, include_class)
elif isinstance(t, StaticMethod):
return 'void' # TODO: is it correct to ignore StaticMethod?
elif isinstance(t, List):
item_type = self.lltype_to_cts(t._ITEMTYPE)
- return 'class [pypylib]pypy.runtime.List`1<%s>' % item_type
+ return self.__class('[pypylib]pypy.runtime.List`1<%s>' % item_type, include_class)
return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t)
@@ -75,7 +80,7 @@
ret_type, ret_var = self.llvar_to_cts(graph.getreturnvar())
func_name = func_name or graph.name
- args = graph.getargs()
+ args = [arg for arg in graph.getargs() if arg.concretetype is not Void]
if is_method:
args = args[1:]
@@ -108,6 +113,3 @@
return parts
else:
return None, parts[0]
-
- def pyexception_to_cts(self, exc):
- return _get_from_dict(_pyexception_to_cts, exc, 'Unknown exception %s' % exc)
Modified: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- pypy/dist/pypy/translator/cli/database.py (original)
+++ pypy/dist/pypy/translator/cli/database.py Wed Apr 12 18:29:32 2006
@@ -19,6 +19,7 @@
self.functions = {} # graph --> function_name
self.methods = {} # graph --> method_name
self.consts = {} # value --> const_name
+ self.const_names = set()
def pending_function(self, graph):
self.pending_node(Function(self, graph))
@@ -48,8 +49,11 @@
try:
name = self.consts[const]
except KeyError:
- name = const.get_name(len(self.consts))
+ name = const.get_name()
+ if name in self.const_names:
+ name += '__%d' % len(self.consts)
self.consts[const] = name
+ self.const_names.add(name)
return '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, name)
@@ -90,7 +94,7 @@
assert False, 'Unknown constant: %s' % const
make = staticmethod(make)
- def get_name(self, n):
+ def get_name(self):
pass
def get_type(self):
@@ -115,9 +119,8 @@
def __eq__(self, other):
return self.obj == other.obj
- def get_name(self, n):
- name = self.obj._TYPE._name.replace('.', '_')
- return '%s_%d' % (name, n)
+ def get_name(self):
+ return self.obj._TYPE._name.replace('.', '_')
def get_type(self):
return self.cts.lltype_to_cts(self.static_type)
Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py (original)
+++ pypy/dist/pypy/translator/cli/function.py Wed Apr 12 18:29:32 2006
@@ -56,7 +56,7 @@
if self.is_method:
args = self.args[1:] # self is implicit
- meth_type = 'virtual'
+ meth_type = 'virtual' # TODO: mark as virtual only when strictly necessary
else:
args = self.args
meth_type = 'static'
@@ -100,7 +100,12 @@
continue # see above
assert issubclass(link.exitcase, Exception)
- cts_exc = self.cts.pyexception_to_cts(link.exitcase)
+ #cts_exc = self.cts.pyexception_to_cts(link.exitcase)
+ #cts_exc = str(link.exitcase) # TODO: is it a bit hackish?
+ ll_meta_exc = link.llexitcase
+ self.db.record_const(ll_meta_exc)
+ ll_exc = ll_meta_exc._inst.class_._INSTANCE
+ cts_exc = self.cts.lltype_to_cts(ll_exc, False)
self.ilasm.begin_catch(cts_exc)
target = link.target
@@ -198,7 +203,8 @@
self.locals = locals
def _set_args(self):
- self.args = map(self.cts.llvar_to_cts, self.graph.getargs())
+ args = [arg for arg in self.graph.getargs() if arg.concretetype is not Void]
+ self.args = map(self.cts.llvar_to_cts, args)
self.argset = set([argname for argtype, argname in self.args])
def _get_block_name(self, block):
@@ -257,9 +263,7 @@
self.ilasm.call(signature)
def cast_to(self, lltype):
- cts_type = self.cts.lltype_to_cts(lltype)
- if cts_type.startswith('class '):
- cts_type = cts_type[len('class '):]
+ cts_type = self.cts.lltype_to_cts(lltype, False)
self.ilasm.opcode('castclass', cts_type)
def new(self, obj):
Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py (original)
+++ pypy/dist/pypy/translator/cli/metavm.py Wed Apr 12 18:29:32 2006
@@ -28,6 +28,9 @@
def render(self, generator, op):
pass
+ def __str__(self):
+ return self.__class__.__name__
+
class PushArg(MicroInstruction):
def __init__(self, n):
Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py (original)
+++ pypy/dist/pypy/translator/cli/opcodes.py Wed Apr 12 18:29:32 2006
@@ -11,6 +11,29 @@
def _abs(type_):
return [PushAllArgs, 'call %s class [mscorlib]System.Math::Abs(%s)' % (type_, type_)]
+def _check(op):
+ if isinstance(op, str):
+ op = [PushAllArgs, op, StoreResult]
+
+ label = '__check_block_%d' % _check.count
+ _check.count += 1
+
+ return [
+ '.try {'
+ ] + op + [ # do the real operations
+ 'leave %s }' % label, # continue normal execution
+
+ # if overflow, raise a pypy's OverflowError
+ 'catch [mscorlib]System.OverflowException {',
+ 'newobj instance void class exceptions.OverflowError::.ctor()',
+ 'dup',
+ 'ldsfld class Object_meta pypy.runtime.Constants::exceptions_OverflowError_meta',
+ 'stfld class Object_meta Object::meta',
+ 'throw }',
+
+ '%s: nop' % label # continue normal execution
+ ]
+_check.count = 0
opcodes = {
# __________ object oriented operations __________
@@ -21,6 +44,7 @@
'oosend': [CallMethod],
'ooupcast': DoNothing,
'oodowncast': DoNothing, # TODO: is it really safe?
+ 'oois': 'ceq',
'same_as': DoNothing, # TODO: does same_as really do nothing else than renaming?
@@ -43,9 +67,9 @@
'int_is_true': DoNothing,
'int_neg': 'neg',
- 'int_neg_ovf': ['ldc.i4.0', PushAllArgs, 'sub.ovf'],
+ 'int_neg_ovf': _check(['ldc.i4.0', PushAllArgs, 'sub.ovf', StoreResult]),
'int_abs': _abs('int32'),
- 'int_abs_ovf': _abs('int32'),
+ 'int_abs_ovf': _check(_abs('int32')),
'int_invert': 'not',
'int_add': 'add',
@@ -64,9 +88,9 @@
'int_lshift': 'shl',
'int_rshift': 'shr',
'int_xor': 'xor',
- 'int_add_ovf': 'add.ovf',
- 'int_sub_ovf': 'sub.ovf',
- 'int_mul_ovf': 'mul.ovf',
+ 'int_add_ovf': _check('add.ovf'),
+ 'int_sub_ovf': _check('sub.ovf'),
+ 'int_mul_ovf': _check('mul.ovf'),
'int_floordiv_ovf': 'div', # these can't overflow!
'int_mod_ovf': 'rem',
'int_lt_ovf': 'clt',
@@ -79,8 +103,8 @@
'int_or_ovf': 'or',
# are they the same?
- 'int_lshift_ovf': [PushArg(0), 'conv.i8', PushArg(1), 'shl', 'conv.ovf.i4'],
- 'int_lshift_ovf_val': [PushArg(0), 'conv.i8', PushArg(1), 'shl', 'conv.ovf.i4'],
+ 'int_lshift_ovf': _check([PushArg(0),'conv.i8',PushArg(1), 'shl', 'conv.ovf.i4', StoreResult]),
+ 'int_lshift_ovf_val': _check([PushArg(0),'conv.i8',PushArg(1), 'shl', 'conv.ovf.i4', StoreResult]),
'int_rshift_ovf': 'shr', # these can't overflow!
'int_xor_ovf': 'xor',
@@ -191,7 +215,10 @@
if type(value) is str:
value = InstructionList([PushAllArgs, value, StoreResult])
elif value is not None:
- value = InstructionList(value + [StoreResult])
-
+ if StoreResult not in value:
+ value.append(StoreResult)
+ value = InstructionList(value)
+
opcodes[key] = value
+
Modified: pypy/dist/pypy/translator/cli/test/compile.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/compile.py (original)
+++ pypy/dist/pypy/translator/cli/test/compile.py Wed Apr 12 18:29:32 2006
@@ -24,53 +24,16 @@
print 'OK'
-class MyClass:
- INCREMENT = 1
-
- def __init__(self, x, y):
- self.x = x
- self.y = y
-
- def compute(self):
- return self.x + self.y
-
- def compute_and_multiply(self, factor):
- return self.compute() * factor
-
- def static_meth(x, y):
- return x*y
- static_meth = staticmethod(static_meth)
-
-## def class_meth(cls, x, y):
-## return x*y + cls.INCREMENT
-## class_meth = classmethod(class_meth)
-
- def class_attribute(self):
- return self.x + self.INCREMENT
-
-class MyDerivedClass(MyClass):
- INCREMENT = 2
-
- def __init__(self, x, y):
- MyClass.__init__(self, x+12, y+34)
-
- def compute(self):
- return self.x - self.y
-
-
-
-def init_and_compute(cls, x, y):
- return cls(x, y).compute()
-
-
def bar(x, y):
- return init_and_compute(MyClass, x, y) + init_and_compute(MyDerivedClass, x, y)
-
+ try:
+ return ovfcheck(x+y)
+ except OverflowError:
+ return 0
f = compile_function(bar, [int, int])
try:
- check(bar, f, 42, 13)
+ check(bar, f, sys.maxint, 13)
except py.test.Item.Skipped:
print 'Test skipped'
More information about the Pypy-commit
mailing list