Author: Ronan Lamy <[email protected]>
Branch:
Changeset: r65342:7ba260941669
Date: 2013-07-11 13:06 +0200
http://bitbucket.org/pypy/pypy/changeset/7ba260941669/
Log: Merge branch flowoperators
diff --git a/rpython/config/translationoption.py
b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -170,7 +170,6 @@
cmdline="--make-jobs", default=detect_number_of_processors()),
# Flags of the TranslationContext:
- BoolOption("simplifying", "Simplify flow graphs", default=True),
BoolOption("list_comprehension_operations",
"When true, look for and special-case the sequence of "
"operations that results from a list comprehension and "
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -14,7 +14,7 @@
recursively_flatten)
from rpython.flowspace.specialcase import (rpython_print_item,
rpython_print_newline)
-from rpython.flowspace.operation import implicit_exceptions
+from rpython.flowspace.operation import op
class FlowingError(Exception):
@@ -55,25 +55,44 @@
pass
class SpamBlock(Block):
- # make slots optional, for debugging
- if hasattr(Block, '__slots__'):
- __slots__ = "dead framestate".split()
-
def __init__(self, framestate):
Block.__init__(self, framestate.getvariables())
self.framestate = framestate
self.dead = False
+ def make_recorder(self):
+ return BlockRecorder(self)
+
class EggBlock(Block):
- # make slots optional, for debugging
- if hasattr(Block, '__slots__'):
- __slots__ = "prevblock booloutcome last_exception".split()
-
def __init__(self, inputargs, prevblock, booloutcome):
Block.__init__(self, inputargs)
self.prevblock = prevblock
self.booloutcome = booloutcome
+ @property
+ def ancestor(self):
+ parent = self.prevblock
+ while isinstance(parent, EggBlock):
+ parent = parent.prevblock
+ return parent
+
+ @property
+ def dead(self):
+ return self.ancestor.dead
+
+ @property
+ def framestate(self):
+ return self.ancestor.framestate
+
+ def make_recorder(self):
+ recorder = BlockRecorder(self)
+ curr = self
+ while isinstance(curr, EggBlock):
+ prev = curr.prevblock
+ recorder = Replayer(prev, curr.booloutcome, recorder)
+ curr = prev
+ return recorder
+
def extravars(self, last_exception=None, last_exc_value=None):
self.last_exception = last_exception
@@ -209,6 +228,7 @@
w_exc_cls, w_exc_value = egg.inputargs[-2:]
if isinstance(egg.last_exception, Constant):
w_exc_cls = egg.last_exception
+ assert not isinstance(w_exc_cls.value, list)
raise ImplicitOperationError(w_exc_cls, w_exc_value)
# ____________________________________________________________
@@ -430,44 +450,23 @@
self.last_instr = state.next_instr
self.blockstack = state.blocklist[:]
- def recording(self, block):
- """ Setup recording of the block and return the recorder. """
- parentblocks = []
- parent = block
- while isinstance(parent, EggBlock):
- parent = parent.prevblock
- parentblocks.append(parent)
- # parentblocks = [Egg, Egg, ..., Egg, Spam] not including block
- if parent.dead:
- raise StopFlowing
- self.setstate(parent.framestate)
- recorder = BlockRecorder(block)
- prevblock = block
- for parent in parentblocks:
- recorder = Replayer(parent, prevblock.booloutcome, recorder)
- prevblock = parent
- return recorder
+ def guessbool(self, w_condition, **kwds):
+ return self.recorder.guessbool(self, w_condition, **kwds)
- def record(self, spaceop):
- """Record an operation into the active block"""
+ def do_operation(self, name, *args_w):
recorder = self.recorder
if getattr(recorder, 'final_state', None) is not None:
self.mergeblock(recorder.crnt_block, recorder.final_state)
raise StopFlowing
- recorder.append(spaceop)
-
- def guessbool(self, w_condition, **kwds):
- return self.recorder.guessbool(self, w_condition, **kwds)
-
- def do_operation(self, name, *args_w):
spaceop = SpaceOperation(name, args_w, Variable())
spaceop.offset = self.last_instr
- self.record(spaceop)
+ recorder.append(spaceop)
return spaceop.result
def do_operation_with_implicit_exceptions(self, name, *args_w):
w_result = self.do_operation(name, *args_w)
- self.handle_implicit_exceptions(implicit_exceptions.get(name))
+ oper = getattr(op, name)
+ self.handle_implicit_exceptions(oper.canraise)
return w_result
def handle_implicit_exceptions(self, exceptions):
@@ -488,39 +487,44 @@
self.pendingblocks = collections.deque([graph.startblock])
while self.pendingblocks:
block = self.pendingblocks.popleft()
- try:
- self.recorder = self.recording(block)
- while True:
- self.last_instr = self.handle_bytecode(self.last_instr)
- self.recorder.final_state = self.getstate()
+ if not block.dead:
+ self.record_block(block)
- except ImplicitOperationError, e:
- if isinstance(e.w_type, Constant):
- exc_cls = e.w_type.value
- else:
- exc_cls = Exception
- msg = "implicit %s shouldn't occur" % exc_cls.__name__
- w_type = Constant(AssertionError)
- w_value = Constant(AssertionError(msg))
- link = Link([w_type, w_value], graph.exceptblock)
- self.recorder.crnt_block.closeblock(link)
+ def record_block(self, block):
+ self.setstate(block.framestate)
+ self.recorder = block.make_recorder()
+ try:
+ while True:
+ self.last_instr = self.handle_bytecode(self.last_instr)
+ self.recorder.final_state = self.getstate()
- except FSException, e:
- if e.w_type is self.space.w_ImportError:
- msg = 'import statement always raises %s' % e
- raise ImportError(msg)
- link = Link([e.w_type, e.w_value], graph.exceptblock)
- self.recorder.crnt_block.closeblock(link)
+ except ImplicitOperationError, e:
+ if isinstance(e.w_type, Constant):
+ exc_cls = e.w_type.value
+ else:
+ exc_cls = Exception
+ msg = "implicit %s shouldn't occur" % exc_cls.__name__
+ w_type = Constant(AssertionError)
+ w_value = Constant(AssertionError(msg))
+ link = Link([w_type, w_value], self.graph.exceptblock)
+ self.recorder.crnt_block.closeblock(link)
- except StopFlowing:
- pass
+ except FSException, e:
+ if e.w_type == self.space.w_ImportError:
+ msg = 'import statement always raises %s' % e
+ raise ImportError(msg)
+ link = Link([e.w_type, e.w_value], self.graph.exceptblock)
+ self.recorder.crnt_block.closeblock(link)
- except Return as exc:
- w_result = exc.value
- link = Link([w_result], graph.returnblock)
- self.recorder.crnt_block.closeblock(link)
+ except StopFlowing:
+ pass
- del self.recorder
+ except Return as exc:
+ w_result = exc.value
+ link = Link([w_result], self.graph.returnblock)
+ self.recorder.crnt_block.closeblock(link)
+
+ self.recorder = None
def mergeblock(self, currentblock, currentstate):
next_instr = currentstate.next_instr
@@ -661,8 +665,8 @@
self.last_exception = operr
raise operr
else:
- raise FSException(space.w_TypeError,
- space.wrap("raise: no active exception to re-raise"))
+ raise space.exc_wrap(TypeError(
+ "raise: no active exception to re-raise"))
w_value = space.w_None
if nbargs >= 3:
diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py
--- a/rpython/flowspace/model.py
+++ b/rpython/flowspace/model.py
@@ -3,6 +3,7 @@
#
# the below object/attribute model evolved from
# a discussion in Berlin, 4th of october 2003
+import types
import py
from rpython.tool.uid import uid, Hashable
@@ -261,6 +262,7 @@
dummyname = 'v'
namesdict = {dummyname : (dummyname, 0)}
+ @property
def name(self):
_name = self._name
_nr = self._nr
@@ -270,11 +272,10 @@
_nr = self._nr = nd[_name][1]
nd[_name] = (_name, _nr + 1)
return "%s%d" % (_name, _nr)
- name = property(name)
+ @property
def renamed(self):
return self._name is not self.dummyname
- renamed = property(renamed)
def __init__(self, name=None):
self._name = self.dummyname
@@ -314,6 +315,9 @@
self._name = intern(name)
self._nr = nr
+ def foldable(self):
+ return False
+
class Constant(Hashable):
__slots__ = ["concretetype"]
@@ -323,6 +327,25 @@
if concretetype is not None:
self.concretetype = concretetype
+ def foldable(self):
+ to_check = self.value
+ if hasattr(to_check, 'im_self'):
+ to_check = to_check.im_self
+ if isinstance(to_check, (type, types.ClassType, types.ModuleType)):
+ # classes/types/modules are assumed immutable
+ return True
+ if (hasattr(to_check, '__class__') and
+ to_check.__class__.__module__ == '__builtin__'):
+ # builtin object
+ return True
+ # User-created instance
+ if hasattr(to_check, '_freeze_'):
+ assert to_check._freeze_() is True
+ return True
+ else:
+ # cannot count on it not mutating at runtime!
+ return False
+
class UnwrapException(Exception):
"""Attempted to unwrap a Variable."""
diff --git a/rpython/flowspace/objspace.py b/rpython/flowspace/objspace.py
--- a/rpython/flowspace/objspace.py
+++ b/rpython/flowspace/objspace.py
@@ -19,7 +19,7 @@
from rpython.flowspace.pygraph import PyGraph
from rpython.flowspace.specialcase import SPECIAL_CASES
from rpython.rlib.unroll import unrolling_iterable, _unroller
-from rpython.rlib import rstackovf, rarithmetic
+from rpython.rlib import rstackovf
from rpython.rlib.rarithmetic import is_valid_int
@@ -45,6 +45,16 @@
}
}
+# built-ins that can always raise exceptions
+builtins_exceptions = {
+ int: [ValueError],
+ float: [ValueError],
+ chr: [ValueError],
+ unichr: [ValueError],
+ unicode: [UnicodeDecodeError],
+}
+
+
def _assert_rpythonic(func):
"""Raise ValueError if ``func`` is obviously not RPython"""
if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'):
@@ -135,6 +145,11 @@
raise WrapException
return Constant(obj)
+ def exc_wrap(self, exc):
+ w_value = self.wrap(exc)
+ w_type = self.wrap(type(exc))
+ return FSException(w_type, w_value)
+
def int_w(self, w_obj):
if isinstance(w_obj, Constant):
val = w_obj.value
@@ -143,15 +158,6 @@
return val
return self.unwrap(w_obj)
- def uint_w(self, w_obj):
- if isinstance(w_obj, Constant):
- val = w_obj.value
- if type(val) is not rarithmetic.r_uint:
- raise TypeError("expected unsigned: " + repr(w_obj))
- return val
- return self.unwrap(w_obj)
-
-
def str_w(self, w_obj):
if isinstance(w_obj, Constant):
val = w_obj.value
@@ -160,14 +166,6 @@
return val
return self.unwrap(w_obj)
- def float_w(self, w_obj):
- if isinstance(w_obj, Constant):
- val = w_obj.value
- if type(val) is not float:
- raise TypeError("expected float: " + repr(w_obj))
- return val
- return self.unwrap(w_obj)
-
def unwrap(self, w_obj):
if isinstance(w_obj, Variable):
raise UnwrapException
@@ -176,40 +174,9 @@
else:
raise TypeError("not wrapped: " + repr(w_obj))
- def unwrap_for_computation(self, w_obj):
- obj = self.unwrap(w_obj)
- to_check = obj
- if hasattr(to_check, 'im_self'):
- to_check = to_check.im_self
- if (not isinstance(to_check, (type, types.ClassType,
types.ModuleType)) and
- # classes/types/modules are assumed immutable
- hasattr(to_check, '__class__') and to_check.__class__.__module__
!= '__builtin__'):
- frozen = hasattr(to_check, '_freeze_')
- if frozen:
- assert to_check._freeze_() is True
- else:
- # cannot count on it not mutating at runtime!
- raise UnwrapException
- return obj
-
def exception_issubclass_w(self, w_cls1, w_cls2):
return self.is_true(self.issubtype(w_cls1, w_cls2))
- def _exception_match(self, w_exc_type, w_check_class):
- """Helper for exception_match
-
- Handles the base case where w_check_class is a constant exception
- type.
- """
- if self.is_w(w_exc_type, w_check_class):
- return True # fast path (also here to handle string exceptions)
- try:
- return self.exception_issubclass_w(w_exc_type, w_check_class)
- except FSException, e:
- if e.match(self, self.w_TypeError): # string exceptions maybe
- return False
- raise
-
def exception_match(self, w_exc_type, w_check_class):
"""Checks if the given exception type matches 'w_check_class'."""
try:
@@ -221,47 +188,43 @@
"Catching %s is not valid in RPython" % check_class.__name__)
if not isinstance(check_class, tuple):
# the simple case
- return self._exception_match(w_exc_type, w_check_class)
+ return self.exception_issubclass_w(w_exc_type, w_check_class)
# special case for StackOverflow (see rlib/rstackovf.py)
if check_class == rstackovf.StackOverflow:
w_real_class = self.wrap(rstackovf._StackOverflow)
- return self._exception_match(w_exc_type, w_real_class)
+ return self.exception_issubclass_w(w_exc_type, w_real_class)
# checking a tuple of classes
for w_klass in self.unpackiterable(w_check_class):
if self.exception_match(w_exc_type, w_klass):
return True
return False
- def exc_from_raise(self, w_type, w_value):
+ def exc_from_raise(self, w_arg1, w_arg2):
"""
Create a wrapped exception from the arguments of a raise statement.
Returns an FSException object whose w_value is an instance of w_type.
"""
- if self.isinstance_w(w_type, self.w_type):
+ if self.isinstance_w(w_arg1, self.w_type):
# this is for all cases of the form (Class, something)
- if self.is_w(w_value, self.w_None):
+ if self.is_w(w_arg2, self.w_None):
# raise Type: we assume we have to instantiate Type
- w_value = self.call_function(w_type)
- w_type = self.type(w_value)
+ w_value = self.call_function(w_arg1)
else:
- w_valuetype = self.type(w_value)
- if self.exception_issubclass_w(w_valuetype, w_type):
+ w_valuetype = self.type(w_arg2)
+ if self.exception_issubclass_w(w_valuetype, w_arg1):
# raise Type, Instance: let etype be the exact type of
value
- w_type = w_valuetype
+ w_value = w_arg2
else:
# raise Type, X: assume X is the constructor argument
- w_value = self.call_function(w_type, w_value)
- w_type = self.type(w_value)
+ w_value = self.call_function(w_arg1, w_arg2)
else:
# the only case left here is (inst, None), from a 'raise inst'.
- w_inst = w_type
- w_instclass = self.type(w_inst)
- if not self.is_w(w_value, self.w_None):
- raise FSException(self.w_TypeError, self.wrap(
+ if not self.is_w(w_arg2, self.w_None):
+ raise self.exc_wrap(TypeError(
"instance exception may not have a separate value"))
- w_value = w_inst
- w_type = w_instclass
+ w_value = w_arg1
+ w_type = self.type(w_value)
return FSException(w_type, w_value)
def unpackiterable(self, w_iterable):
@@ -291,12 +254,8 @@
return self.wrap(not self.is_true(w_obj))
def is_true(self, w_obj):
- try:
- obj = self.unwrap_for_computation(w_obj)
- except UnwrapException:
- pass
- else:
- return bool(obj)
+ if w_obj.foldable():
+ return bool(w_obj.value)
w_truthvalue = self.frame.do_operation('is_true', w_obj)
return self.frame.guessbool(w_truthvalue)
@@ -316,7 +275,7 @@
try:
v, next_unroller = it.step()
except IndexError:
- raise FSException(self.w_StopIteration, self.w_None)
+ raise self.exc_wrap(StopIteration())
else:
frame.replace_in_stack(it, next_unroller)
return self.wrap(v)
@@ -324,16 +283,6 @@
frame.handle_implicit_exceptions([StopIteration, RuntimeError])
return w_item
- def setitem(self, w_obj, w_key, w_val):
- # protect us from globals write access
- if w_obj is self.frame.w_globals:
- raise FlowingError(self.frame,
- "Attempting to modify global variable %r." % (w_key))
- return self.frame.do_operation_with_implicit_exceptions('setitem',
- w_obj, w_key, w_val)
-
- def setitem_str(self, w_obj, key, w_value):
- return self.setitem(w_obj, self.wrap(key), w_value)
def getattr(self, w_obj, w_name):
# handling special things like sys
@@ -343,12 +292,8 @@
if w_name not in const_w:
return
self.frame.do_operation_with_implicit_exceptions('getattr',
w_obj, w_name)
- try:
- obj = self.unwrap_for_computation(w_obj)
- name = self.unwrap_for_computation(w_name)
- except UnwrapException:
- pass
- else:
+ if w_obj.foldable() and w_name.foldable():
+ obj, name = w_obj.value, w_name.value
try:
result = getattr(obj, name)
except Exception, e:
@@ -369,8 +314,8 @@
def import_name(self, name, glob=None, loc=None, frm=None, level=-1):
try:
mod = __import__(name, glob, loc, frm, level)
- except ImportError, e:
- raise FSException(self.w_ImportError, self.wrap(str(e)))
+ except ImportError as e:
+ raise self.exc_wrap(e)
return self.wrap(mod)
def import_from(self, w_module, w_name):
@@ -378,15 +323,15 @@
assert isinstance(w_name, Constant)
# handle sys
if w_module in self.not_really_const:
- const_w = self.not_really_const[w_obj]
+ const_w = self.not_really_const[w_module]
if w_name not in const_w:
return
self.frame.do_operation_with_implicit_exceptions('getattr',
- w_obj, w_name)
+ w_module,
w_name)
try:
return self.wrap(getattr(w_module.value, w_name.value))
except AttributeError:
- raise FSException(self.w_ImportError,
- self.wrap("cannot import name '%s'" % w_name.value))
+ raise self.exc_wrap(ImportError(
+ "cannot import name '%s'" % w_name.value))
def call_method(self, w_obj, methname, *arg_w):
w_meth = self.getattr(w_obj, self.wrap(methname))
@@ -417,7 +362,7 @@
args_w = args.arguments_w +
self.unpackiterable(args.w_stararg)
else:
args_w = args.arguments_w
- return sc(self, fn, args_w)
+ return sc(self, args_w)
if args.keywords or isinstance(args.w_stararg, Variable):
shape, args_w = args.flatten()
@@ -430,15 +375,6 @@
args_w = args.arguments_w
w_res = self.frame.do_operation('simple_call', w_callable, *args_w)
- # maybe the call has generated an exception (any one)
- # but, let's say, not if we are calling a built-in class or function
- # because this gets in the way of the special-casing of
- #
- # raise SomeError(x)
- #
- # as shown by test_objspace.test_raise3.
-
- exceptions = [Exception] # *any* exception by default
if isinstance(w_callable, Constant):
c = w_callable.value
if (isinstance(c, (types.BuiltinFunctionType,
@@ -446,8 +382,11 @@
types.ClassType,
types.TypeType)) and
c.__module__ in ['__builtin__', 'exceptions']):
- exceptions = operation.implicit_exceptions.get(c)
- self.frame.handle_implicit_exceptions(exceptions)
+ if c in builtins_exceptions:
+
self.frame.handle_implicit_exceptions(builtins_exceptions[c])
+ return w_res
+ # *any* exception for non-builtins
+ self.frame.handle_implicit_exceptions([Exception])
return w_res
def find_global(self, w_globals, varname):
@@ -462,82 +401,61 @@
raise FlowingError(self.frame, self.wrap(message))
return self.wrap(value)
-def make_op(name, arity):
+def make_impure_op(oper):
+ def generic_operator(self, *args_w):
+ if len(args_w) != oper.arity:
+ raise TypeError(oper.name + " got the wrong number of arguments")
+ w_result = self.frame.do_operation_with_implicit_exceptions(oper.name,
*args_w)
+ return w_result
+ return generic_operator
+
+def make_op(oper):
"""Add function operation to the flow space."""
- if getattr(FlowObjSpace, name, None) is not None:
- return
-
- op = None
- skip = False
- arithmetic = False
-
- if (name.startswith('del') or
- name.startswith('set') or
- name.startswith('inplace_')):
- # skip potential mutators
- skip = True
- elif name in ('id', 'hash', 'iter', 'userdel'):
- # skip potential runtime context dependecies
- skip = True
- elif name in ('repr', 'str'):
- rep = getattr(__builtin__, name)
- def op(obj):
- s = rep(obj)
- if "at 0x" in s:
- print >>sys.stderr, "Warning: captured address may be awkward"
- return s
- else:
- op = operation.FunctionByName[name]
- arithmetic = (name + '_ovf') in operation.FunctionByName
-
- if not op and not skip:
- raise ValueError("XXX missing operator: %s" % (name,))
+ name = oper.name
+ func = oper.pyfunc
def generic_operator(self, *args_w):
- assert len(args_w) == arity, name + " got the wrong number of
arguments"
- if op:
- args = []
- for w_arg in args_w:
- try:
- arg = self.unwrap_for_computation(w_arg)
- except UnwrapException:
- break
+ assert len(args_w) == oper.arity, name + " got the wrong number of
arguments"
+ args = []
+ if all(w_arg.foldable() for w_arg in args_w):
+ args = [w_arg.value for w_arg in args_w]
+ # All arguments are constants: call the operator now
+ try:
+ result = func(*args)
+ except Exception, e:
+ etype = e.__class__
+ msg = "%s%r always raises %s: %s" % (
+ name, tuple(args), etype, e)
+ raise FlowingError(self.frame, msg)
+ else:
+ # don't try to constant-fold operations giving a 'long'
+ # result. The result is probably meant to be sent to
+ # an intmask(), but the 'long' constant confuses the
+ # annotator a lot.
+ if oper.can_overflow and type(result) is long:
+ pass
+ # don't constant-fold getslice on lists, either
+ elif name == 'getslice' and type(result) is list:
+ pass
+ # otherwise, fine
else:
- args.append(arg)
- else:
- # All arguments are constants: call the operator now
- try:
- result = op(*args)
- except Exception, e:
- etype = e.__class__
- msg = "%s%r always raises %s: %s" % (
- name, tuple(args), etype, e)
- raise FlowingError(self.frame, msg)
- else:
- # don't try to constant-fold operations giving a 'long'
- # result. The result is probably meant to be sent to
- # an intmask(), but the 'long' constant confuses the
- # annotator a lot.
- if arithmetic and type(result) is long:
+ try:
+ return self.wrap(result)
+ except WrapException:
+ # type cannot sanely appear in flow graph,
+ # store operation with variable result instead
pass
- # don't constant-fold getslice on lists, either
- elif name == 'getslice' and type(result) is list:
- pass
- # otherwise, fine
- else:
- try:
- return self.wrap(result)
- except WrapException:
- # type cannot sanely appear in flow graph,
- # store operation with variable result instead
- pass
w_result = self.frame.do_operation_with_implicit_exceptions(name,
*args_w)
return w_result
+ return generic_operator
- setattr(FlowObjSpace, name, generic_operator)
-
-for (name, symbol, arity, specialnames) in operation.MethodTable:
- make_op(name, arity)
+for oper in operation.op.__dict__.values():
+ if getattr(FlowObjSpace, oper.name, None) is None:
+ if oper.pure:
+ op_method = make_op(oper)
+ else:
+ op_method = make_impure_op(oper)
+ setattr(FlowObjSpace, oper.name, op_method)
def build_flow(func, space=FlowObjSpace()):
diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -8,93 +8,53 @@
import operator
from rpython.tool.sourcetools import compile2
from rpython.rlib.rarithmetic import ovfcheck
+from rpython.flowspace.model import Constant
-# this is a copy that should be shared with standard objspace
+class _OpHolder(object): pass
+op = _OpHolder()
-MethodTable = [
-# method name # symbol # number of arguments # special method name(s)
- ('is_', 'is', 2, []),
- ('id', 'id', 1, []),
- ('type', 'type', 1, []),
- ('isinstance', 'isinstance', 2, ['__instancecheck__']),
- ('issubtype', 'issubtype', 2, ['__subclasscheck__']), # not for
old-style classes
- ('repr', 'repr', 1, ['__repr__']),
- ('str', 'str', 1, ['__str__']),
- ('format', 'format', 2, ['__format__']),
- ('len', 'len', 1, ['__len__']),
- ('hash', 'hash', 1, ['__hash__']),
- ('getattr', 'getattr', 2, ['__getattribute__']),
- ('setattr', 'setattr', 3, ['__setattr__']),
- ('delattr', 'delattr', 2, ['__delattr__']),
- ('getitem', 'getitem', 2, ['__getitem__']),
- ('setitem', 'setitem', 3, ['__setitem__']),
- ('delitem', 'delitem', 2, ['__delitem__']),
- ('getslice', 'getslice', 3, ['__getslice__']),
- ('setslice', 'setslice', 4, ['__setslice__']),
- ('delslice', 'delslice', 3, ['__delslice__']),
- ('trunc', 'trunc', 1, ['__trunc__']),
- ('pos', 'pos', 1, ['__pos__']),
- ('neg', 'neg', 1, ['__neg__']),
- ('nonzero', 'truth', 1, ['__nonzero__']),
- ('abs' , 'abs', 1, ['__abs__']),
- ('hex', 'hex', 1, ['__hex__']),
- ('oct', 'oct', 1, ['__oct__']),
- ('ord', 'ord', 1, []),
- ('invert', '~', 1, ['__invert__']),
- ('add', '+', 2, ['__add__', '__radd__']),
- ('sub', '-', 2, ['__sub__', '__rsub__']),
- ('mul', '*', 2, ['__mul__', '__rmul__']),
- ('truediv', '/', 2, ['__truediv__', '__rtruediv__']),
- ('floordiv', '//', 2, ['__floordiv__', '__rfloordiv__']),
- ('div', 'div', 2, ['__div__', '__rdiv__']),
- ('mod', '%', 2, ['__mod__', '__rmod__']),
- ('divmod', 'divmod', 2, ['__divmod__', '__rdivmod__']),
- ('pow', '**', 3, ['__pow__', '__rpow__']),
- ('lshift', '<<', 2, ['__lshift__', '__rlshift__']),
- ('rshift', '>>', 2, ['__rshift__', '__rrshift__']),
- ('and_', '&', 2, ['__and__', '__rand__']),
- ('or_', '|', 2, ['__or__', '__ror__']),
- ('xor', '^', 2, ['__xor__', '__rxor__']),
- ('int', 'int', 1, ['__int__']),
- ('index', 'index', 1, ['__index__']),
- ('float', 'float', 1, ['__float__']),
- ('long', 'long', 1, ['__long__']),
- ('inplace_add', '+=', 2, ['__iadd__']),
- ('inplace_sub', '-=', 2, ['__isub__']),
- ('inplace_mul', '*=', 2, ['__imul__']),
- ('inplace_truediv', '/=', 2, ['__itruediv__']),
- ('inplace_floordiv','//=', 2, ['__ifloordiv__']),
- ('inplace_div', 'div=', 2, ['__idiv__']),
- ('inplace_mod', '%=', 2, ['__imod__']),
- ('inplace_pow', '**=', 2, ['__ipow__']),
- ('inplace_lshift', '<<=', 2, ['__ilshift__']),
- ('inplace_rshift', '>>=', 2, ['__irshift__']),
- ('inplace_and', '&=', 2, ['__iand__']),
- ('inplace_or', '|=', 2, ['__ior__']),
- ('inplace_xor', '^=', 2, ['__ixor__']),
- ('lt', '<', 2, ['__lt__', '__gt__']),
- ('le', '<=', 2, ['__le__', '__ge__']),
- ('eq', '==', 2, ['__eq__', '__eq__']),
- ('ne', '!=', 2, ['__ne__', '__ne__']),
- ('gt', '>', 2, ['__gt__', '__lt__']),
- ('ge', '>=', 2, ['__ge__', '__le__']),
- ('cmp', 'cmp', 2, ['__cmp__']), # rich cmps preferred
- ('coerce', 'coerce', 2, ['__coerce__', '__coerce__']),
- ('contains', 'contains', 2, ['__contains__']),
- ('iter', 'iter', 1, ['__iter__']),
- ('next', 'next', 1, ['next']),
-# ('call', 'call', 3, ['__call__']),
- ('get', 'get', 3, ['__get__']),
- ('set', 'set', 3, ['__set__']),
- ('delete', 'delete', 2, ['__delete__']),
- ('userdel', 'del', 1, ['__del__']),
- ('buffer', 'buffer', 1, ['__buffer__']), # see buffer.py
- ]
+func2op = {}
+class SpaceOperator(object):
+ def __init__(self, name, arity, symbol, pyfunc, pure=False,
+ can_overflow=False):
+ self.name = name
+ self.arity = arity
+ self.symbol = symbol
+ self.pyfunc = pyfunc
+ self.pure = pure
+ self.can_overflow = can_overflow
+ self.canraise = []
-FunctionByName = {} # dict {"operation_name": <built-in function>}
-OperationName = {} # dict {<built-in function>: "operation_name"}
-Arity = {} # dict {"operation name": number of arguments}
+ def make_sc(self):
+ def sc_operator(space, args_w):
+ if len(args_w) != self.arity:
+ if self is op.pow and len(args_w) == 2:
+ args_w = args_w + [Constant(None)]
+ elif self is op.getattr and len(args_w) == 3:
+ return space.frame.do_operation('simple_call',
Constant(getattr), *args_w)
+ else:
+ raise Exception("should call %r with exactly %d arguments"
% (
+ self.name, self.arity))
+ # completely replace the call with the underlying
+ # operation and its limited implicit exceptions semantic
+ return getattr(space, self.name)(*args_w)
+ return sc_operator
+
+
+def add_operator(name, arity, symbol, pyfunc=None, pure=False, ovf=False):
+ operator_func = getattr(operator, name, None)
+ oper = SpaceOperator(name, arity, symbol, pyfunc, pure, can_overflow=ovf)
+ setattr(op, name, oper)
+ if pyfunc is not None:
+ func2op[pyfunc] = oper
+ if operator_func:
+ func2op[operator_func] = oper
+ if pyfunc is None:
+ oper.pyfunc = operator_func
+ if ovf:
+ ovf_func = lambda *args: ovfcheck(oper.pyfunc(*args))
+ add_operator(name + '_ovf', arity, symbol, pyfunc=ovf_func)
# ____________________________________________________________
@@ -186,33 +146,6 @@
def userdel(x):
x.__del__()
-def neg_ovf(x):
- return ovfcheck(-x)
-
-def abs_ovf(x):
- return ovfcheck(abs(x))
-
-def add_ovf(x, y):
- return ovfcheck(x + y)
-
-def sub_ovf(x, y):
- return ovfcheck(x - y)
-
-def mul_ovf(x, y):
- return ovfcheck(x * y)
-
-def floordiv_ovf(x, y):
- return ovfcheck(operator.floordiv(x, y))
-
-def div_ovf(x, y):
- return ovfcheck(operator.div(x, y))
-
-def mod_ovf(x, y):
- return ovfcheck(x % y)
-
-def lshift_ovf(x, y):
- return ovfcheck(x << y)
-
# slicing: operator.{get,set,del}slice() don't support b=None or c=None
def do_getslice(a, b, c):
return a[b:c]
@@ -226,101 +159,91 @@
def unsupported(*args):
raise ValueError("this is not supported")
-# ____________________________________________________________
-# The following table can list several times the same operation name,
-# if multiple built-in functions correspond to it. The first one should
-# be picked, though, as the best built-in for the given operation name.
-# Lines ('name', operator.name) are added automatically.
+add_operator('is_', 2, 'is', pure=True)
+add_operator('id', 1, 'id', pyfunc=id)
+add_operator('type', 1, 'type', pyfunc=new_style_type, pure=True)
+add_operator('isinstance', 2, 'isinstance', pyfunc=isinstance, pure=True)
+add_operator('issubtype', 2, 'issubtype', pyfunc=issubclass, pure=True) # not
for old-style classes
+add_operator('repr', 1, 'repr', pyfunc=repr, pure=True)
+add_operator('str', 1, 'str', pyfunc=str, pure=True)
+add_operator('format', 2, 'format', pyfunc=unsupported)
+add_operator('len', 1, 'len', pyfunc=len, pure=True)
+add_operator('hash', 1, 'hash', pyfunc=hash)
+add_operator('getattr', 2, 'getattr', pyfunc=getattr, pure=True)
+add_operator('setattr', 3, 'setattr', pyfunc=setattr)
+add_operator('delattr', 2, 'delattr', pyfunc=delattr)
+add_operator('getitem', 2, 'getitem', pure=True)
+add_operator('setitem', 3, 'setitem')
+add_operator('delitem', 2, 'delitem')
+add_operator('getslice', 3, 'getslice', pyfunc=do_getslice, pure=True)
+add_operator('setslice', 4, 'setslice', pyfunc=do_setslice)
+add_operator('delslice', 3, 'delslice', pyfunc=do_delslice)
+add_operator('trunc', 1, 'trunc', pyfunc=unsupported)
+add_operator('pos', 1, 'pos', pure=True)
+add_operator('neg', 1, 'neg', pure=True, ovf=True)
+add_operator('nonzero', 1, 'truth', pyfunc=bool, pure=True)
+op.is_true = op.nonzero
+add_operator('abs' , 1, 'abs', pyfunc=abs, pure=True, ovf=True)
+add_operator('hex', 1, 'hex', pyfunc=hex, pure=True)
+add_operator('oct', 1, 'oct', pyfunc=oct, pure=True)
+add_operator('ord', 1, 'ord', pyfunc=ord, pure=True)
+add_operator('invert', 1, '~', pure=True)
+add_operator('add', 2, '+', pure=True, ovf=True)
+add_operator('sub', 2, '-', pure=True, ovf=True)
+add_operator('mul', 2, '*', pure=True, ovf=True)
+add_operator('truediv', 2, '/', pure=True)
+add_operator('floordiv', 2, '//', pure=True, ovf=True)
+add_operator('div', 2, 'div', pure=True, ovf=True)
+add_operator('mod', 2, '%', pure=True, ovf=True)
+add_operator('divmod', 2, 'divmod', pyfunc=divmod, pure=True)
+add_operator('pow', 3, '**', pyfunc=pow, pure=True)
+add_operator('lshift', 2, '<<', pure=True, ovf=True)
+add_operator('rshift', 2, '>>', pure=True)
+add_operator('and_', 2, '&', pure=True)
+add_operator('or_', 2, '|', pure=True)
+add_operator('xor', 2, '^', pure=True)
+add_operator('int', 1, 'int', pyfunc=do_int, pure=True)
+add_operator('index', 1, 'index', pyfunc=do_index, pure=True)
+add_operator('float', 1, 'float', pyfunc=do_float, pure=True)
+add_operator('long', 1, 'long', pyfunc=do_long, pure=True)
+add_operator('inplace_add', 2, '+=', pyfunc=inplace_add)
+add_operator('inplace_sub', 2, '-=', pyfunc=inplace_sub)
+add_operator('inplace_mul', 2, '*=', pyfunc=inplace_mul)
+add_operator('inplace_truediv', 2, '/=', pyfunc=inplace_truediv)
+add_operator('inplace_floordiv', 2, '//=', pyfunc=inplace_floordiv)
+add_operator('inplace_div', 2, 'div=', pyfunc=inplace_div)
+add_operator('inplace_mod', 2, '%=', pyfunc=inplace_mod)
+add_operator('inplace_pow', 2, '**=', pyfunc=inplace_pow)
+add_operator('inplace_lshift', 2, '<<=', pyfunc=inplace_lshift)
+add_operator('inplace_rshift', 2, '>>=', pyfunc=inplace_rshift)
+add_operator('inplace_and', 2, '&=', pyfunc=inplace_and)
+add_operator('inplace_or', 2, '|=', pyfunc=inplace_or)
+add_operator('inplace_xor', 2, '^=', pyfunc=inplace_xor)
+add_operator('lt', 2, '<', pure=True)
+add_operator('le', 2, '<=', pure=True)
+add_operator('eq', 2, '==', pure=True)
+add_operator('ne', 2, '!=', pure=True)
+add_operator('gt', 2, '>', pure=True)
+add_operator('ge', 2, '>=', pure=True)
+add_operator('cmp', 2, 'cmp', pyfunc=cmp, pure=True) # rich cmps preferred
+add_operator('coerce', 2, 'coerce', pyfunc=coerce, pure=True)
+add_operator('contains', 2, 'contains', pure=True)
+add_operator('iter', 1, 'iter', pyfunc=iter)
+add_operator('next', 1, 'next', pyfunc=next)
+#add_operator('call', 3, 'call')
+add_operator('get', 3, 'get', pyfunc=get, pure=True)
+add_operator('set', 3, 'set', pyfunc=set)
+add_operator('delete', 2, 'delete', pyfunc=delete)
+add_operator('userdel', 1, 'del', pyfunc=userdel)
+add_operator('buffer', 1, 'buffer', pyfunc=buffer, pure=True) # see buffer.py
-# INTERNAL ONLY, use the dicts declared at the top of the file.
-Table = [
- ('id', id),
- ('type', new_style_type),
- ('type', type),
- ('isinstance', isinstance),
- ('issubtype', issubclass),
- ('repr', repr),
- ('str', str),
- ('format', unsupported),
- ('len', len),
- ('hash', hash),
- ('getattr', getattr),
- ('setattr', setattr),
- ('delattr', delattr),
- ('nonzero', bool),
- ('nonzero', operator.truth),
- ('is_true', bool),
- ('is_true', operator.truth),
- ('trunc', unsupported),
- ('abs' , abs),
- ('hex', hex),
- ('oct', oct),
- ('ord', ord),
- ('divmod', divmod),
- ('pow', pow),
- ('int', do_int),
- ('index', do_index),
- ('float', do_float),
- ('long', do_long),
- ('inplace_add', inplace_add),
- ('inplace_sub', inplace_sub),
- ('inplace_mul', inplace_mul),
- ('inplace_truediv', inplace_truediv),
- ('inplace_floordiv',inplace_floordiv),
- ('inplace_div', inplace_div),
- ('inplace_mod', inplace_mod),
- ('inplace_pow', inplace_pow),
- ('inplace_lshift', inplace_lshift),
- ('inplace_rshift', inplace_rshift),
- ('inplace_and', inplace_and),
- ('inplace_or', inplace_or),
- ('inplace_xor', inplace_xor),
- ('cmp', cmp),
- ('coerce', coerce),
- ('iter', iter),
- ('next', next),
- ('get', get),
- ('set', set),
- ('delete', delete),
- ('userdel', userdel),
- ('buffer', buffer),
- ('getslice', do_getslice),
- ('setslice', do_setslice),
- ('delslice', do_delslice),
- # --- operations added by graph transformations ---
- ('neg_ovf', neg_ovf),
- ('abs_ovf', abs_ovf),
- ('add_ovf', add_ovf),
- ('sub_ovf', sub_ovf),
- ('mul_ovf', mul_ovf),
- ('floordiv_ovf', floordiv_ovf),
- ('div_ovf', div_ovf),
- ('mod_ovf', mod_ovf),
- ('lshift_ovf', lshift_ovf),
-]
+# Other functions that get directly translated to SpaceOperators
+func2op[type] = op.type
+func2op[operator.truth] = op.nonzero
if hasattr(__builtin__, 'next'):
- Table.append(('next', __builtin__.next))
+ func2op[__builtin__.next] = op.next
-def setup():
- # insert all operators
- for line in MethodTable:
- name = line[0]
- if hasattr(operator, name):
- Table.append((name, getattr(operator, name)))
- # build the dictionaries
- for name, func in Table:
- if name not in FunctionByName:
- FunctionByName[name] = func
- if func not in OperationName:
- OperationName[func] = name
- # check that the result is complete
- for line in MethodTable:
- name = line[0]
- Arity[name] = line[2]
- assert name in FunctionByName
-setup()
-del Table, setup # INTERNAL ONLY, use the dicts declared at the top of the file
op_appendices = {
OverflowError: 'ovf',
@@ -330,24 +253,18 @@
ValueError: 'val',
}
-implicit_exceptions = {
- int: [ValueError], # built-ins that can always raise exceptions
- float: [ValueError],
- chr: [ValueError],
- unichr: [ValueError],
- unicode: [UnicodeDecodeError],
- # specifying IndexError, and KeyError beyond Exception,
- # allows the annotator to be more precise, see
test_reraiseAnything/KeyError in
- # the annotator tests
- 'getitem': [IndexError, KeyError, Exception],
- 'setitem': [IndexError, KeyError, Exception],
- 'delitem': [IndexError, KeyError, Exception],
- 'contains': [Exception], # from an r_dict
- }
+# specifying IndexError, and KeyError beyond Exception,
+# allows the annotator to be more precise, see test_reraiseAnything/KeyError in
+# the annotator tests
+op.getitem.canraise = [IndexError, KeyError, Exception]
+op.setitem.canraise = [IndexError, KeyError, Exception]
+op.delitem.canraise = [IndexError, KeyError, Exception]
+op.contains.canraise = [Exception] # from an r_dict
def _add_exceptions(names, exc):
for name in names.split():
- lis = implicit_exceptions.setdefault(name, [])
+ oper = getattr(op, name)
+ lis = oper.canraise
if exc in lis:
raise ValueError, "your list is causing duplication!"
lis.append(exc)
@@ -356,12 +273,13 @@
def _add_except_ovf(names):
# duplicate exceptions and add OverflowError
for name in names.split():
- lis = implicit_exceptions.setdefault(name, [])[:]
- lis.append(OverflowError)
- implicit_exceptions[name+"_ovf"] = lis
+ oper = getattr(op, name)
+ oper_ovf = getattr(op, name+'_ovf')
+ oper_ovf.canraise = list(oper.canraise)
+ oper_ovf.canraise.append(OverflowError)
_add_exceptions("""div mod divmod truediv floordiv pow
- inplace_div inplace_mod inplace_divmod inplace_truediv
+ inplace_div inplace_mod inplace_truediv
inplace_floordiv inplace_pow""", ZeroDivisionError)
_add_exceptions("""pow inplace_pow lshift inplace_lshift rshift
inplace_rshift""", ValueError)
@@ -370,7 +288,7 @@
inplace_floordiv inplace_div inplace_mod inplace_pow
inplace_lshift""", OverflowError) # without a _ovf version
_add_except_ovf("""neg abs add sub mul
- floordiv div mod pow lshift""") # with a _ovf version
+ floordiv div mod lshift""") # with a _ovf version
_add_exceptions("""pow""",
OverflowError) # for the float case
del _add_exceptions, _add_except_ovf
diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py
--- a/rpython/flowspace/specialcase.py
+++ b/rpython/flowspace/specialcase.py
@@ -1,27 +1,13 @@
from rpython.flowspace.model import Constant
-from rpython.flowspace.operation import OperationName, Arity
+from rpython.flowspace.operation import func2op, op
from rpython.rlib.rarithmetic import r_uint
from rpython.rlib.objectmodel import we_are_translated
-def sc_import(space, fn, args_w):
+def sc_import(space, args_w):
assert len(args_w) > 0 and len(args_w) <= 5, 'import needs 1 to 5
arguments'
args = [space.unwrap(arg) for arg in args_w]
return space.import_name(*args)
-def sc_operator(space, fn, args_w):
- opname = OperationName[fn]
- if len(args_w) != Arity[opname]:
- if opname == 'pow' and len(args_w) == 2:
- args_w = args_w + [Constant(None)]
- elif opname == 'getattr' and len(args_w) == 3:
- return space.frame.do_operation('simple_call', Constant(getattr),
*args_w)
- else:
- raise Exception("should call %r with exactly %d arguments" % (
- fn, Arity[opname]))
- # completely replace the call with the underlying
- # operation and its limited implicit exceptions semantic
- return getattr(space, opname)(*args_w)
-
# _________________________________________________________________________
# a simplified version of the basic printing routines, for RPython programs
class StdOutBuffer:
@@ -47,7 +33,7 @@
# _________________________________________________________________________
-def sc_r_uint(space, r_uint, args_w):
+def sc_r_uint(space, args_w):
# special case to constant-fold r_uint(32-bit-constant)
# (normally, the 32-bit constant is a long, and is not allowed to
# show up in the flow graphs at all)
@@ -56,10 +42,10 @@
return Constant(r_uint(w_value.value))
return space.frame.do_operation('simple_call', space.wrap(r_uint), w_value)
-def sc_we_are_translated(space, we_are_translated, args_w):
+def sc_we_are_translated(space, args_w):
return Constant(True)
-def sc_locals(space, locals, args):
+def sc_locals(space, args):
raise Exception(
"A function calling locals() is not RPython. "
"Note that if you're translating code outside the PyPy "
@@ -71,5 +57,5 @@
SPECIAL_CASES = {__import__: sc_import, r_uint: sc_r_uint,
we_are_translated: sc_we_are_translated,
locals: sc_locals}
-for fn in OperationName:
- SPECIAL_CASES[fn] = sc_operator
+for fn, oper in func2op.items():
+ SPECIAL_CASES[fn] = oper.make_sc()
diff --git a/rpython/flowspace/test/test_objspace.py
b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -1,6 +1,6 @@
from __future__ import with_statement
import new
-import py, sys
+import py
from contextlib import contextmanager
from rpython.flowspace.model import Constant, mkentrymap, c_last_exception
@@ -1169,6 +1169,28 @@
'iter': 1, 'newlist': 1,
'next': 1, 'simple_call': 1}
+ def test_mutate_const_list(self):
+ lst = list('abcdef')
+ def f():
+ lst[0] = 'x'
+ return lst
+ graph = self.codetest(f)
+ assert 'setitem' in self.all_operations(graph)
+
+ def test_sys_getattr(self):
+ def f():
+ import sys
+ return sys.modules
+ graph = self.codetest(f)
+ assert 'getattr' in self.all_operations(graph)
+
+ def test_sys_import_from(self):
+ def f():
+ from sys import modules
+ return modules
+ graph = self.codetest(f)
+ assert 'getattr' in self.all_operations(graph)
+
DATA = {'x': 5,
'y': 6}
diff --git a/rpython/rtyper/lltypesystem/opimpl.py
b/rpython/rtyper/lltypesystem/opimpl.py
--- a/rpython/rtyper/lltypesystem/opimpl.py
+++ b/rpython/rtyper/lltypesystem/opimpl.py
@@ -1,4 +1,4 @@
-from rpython.flowspace.operation import FunctionByName
+from rpython.flowspace.operation import op
from rpython.rlib import debug
from rpython.rlib.rarithmetic import is_valid_int
from rpython.rtyper.lltypesystem import lltype, llmemory
@@ -13,7 +13,6 @@
'lt': True, 'le': True,
'eq': True, 'ne': True,
'is_true': True}
-ops_unary = {'is_true': True, 'neg': True, 'abs': True, 'invert': True}
# global synonyms for some types
from rpython.rlib.rarithmetic import intmask
@@ -46,11 +45,13 @@
def get_primitive_op_src(fullopname):
assert '_' in fullopname, "%s: not a primitive op" % (fullopname,)
typname, opname = fullopname.split('_', 1)
- if opname not in FunctionByName and (opname + '_') in FunctionByName:
- func = FunctionByName[opname + '_'] # or_, and_
+ if hasattr(op, opname):
+ oper = getattr(op, opname)
+ elif hasattr(op, opname + '_'):
+ oper = getattr(op, opname + '_') # or_, and_
else:
- assert opname in FunctionByName, "%s: not a primitive op" %
(fullopname,)
- func = FunctionByName[opname]
+ raise ValueError("%s: not a primitive op" % (fullopname,))
+ func = oper.pyfunc
if typname == 'char':
# char_lt, char_eq, ...
@@ -72,7 +73,7 @@
fullopname,)
argtype = argtype_by_name[typname]
- if opname in ops_unary:
+ if oper.arity == 1:
def op_function(x):
if not isinstance(x, argtype):
raise TypeError("%r arg must be %s, got %r instead" % (
diff --git a/rpython/translator/simplify.py b/rpython/translator/simplify.py
--- a/rpython/translator/simplify.py
+++ b/rpython/translator/simplify.py
@@ -120,7 +120,8 @@
covf = Constant(rarithmetic.ovfcheck)
def check_syntax(opname):
- exlis = operation.implicit_exceptions.get("%s_ovf" % (opname,), [])
+ oper = getattr(operation.op, opname + "_ovf")
+ exlis = oper.canraise
if OverflowError not in exlis:
raise Exception("ovfcheck in %s: Operation %s has no"
" overflow variant" % (graph.name, opname))
@@ -495,11 +496,11 @@
# look for removable operations whose result is never used
for i in range(len(block.operations)-1, -1, -1):
op = block.operations[i]
- if op.result not in read_vars:
+ if op.result not in read_vars:
if canremove(op, block):
del block.operations[i]
- elif op.opname == 'simple_call':
- # XXX we want to have a more effective and safe
+ elif op.opname == 'simple_call':
+ # XXX we want to have a more effective and safe
# way to check if this operation has side effects
# ...
if op.args and isinstance(op.args[0], Constant):
@@ -626,7 +627,7 @@
while candidates:
cand, tgts = candidates.pop()
- newexits = list(cand.exits)
+ newexits = list(cand.exits)
for case, tgt in tgts:
exit = cand.exits[case]
rrenaming = dict(zip(tgt.inputargs,exit.args))
diff --git a/rpython/translator/test/test_translator.py
b/rpython/translator/test/test_translator.py
--- a/rpython/translator/test/test_translator.py
+++ b/rpython/translator/test/test_translator.py
@@ -8,7 +8,7 @@
d['key'] = 'value'
def test_example():
- t = TranslationContext(simplifying=True)
+ t = TranslationContext()
t.buildflowgraph(example)
# this specific example triggered a bug in simplify.py
#t.view()
diff --git a/rpython/translator/translator.py b/rpython/translator/translator.py
--- a/rpython/translator/translator.py
+++ b/rpython/translator/translator.py
@@ -21,7 +21,6 @@
class TranslationContext(object):
FLOWING_FLAGS = {
'verbose': False,
- 'simplifying': True,
'list_comprehension_operations': False, # True, - not super-tested
}
@@ -30,8 +29,7 @@
from rpython.config.translationoption import
get_combined_translation_config
config = get_combined_translation_config(translating=True)
# ZZZ should go away in the end
- for attr in ['verbose', 'simplifying',
- 'list_comprehension_operations']:
+ for attr in ['verbose', 'list_comprehension_operations']:
if attr in flowing_flags:
setattr(config.translation, attr, flowing_flags[attr])
self.config = config
@@ -54,8 +52,7 @@
if self.config.translation.verbose:
log.start(nice_repr_for_func(func))
graph = build_flow(func)
- if self.config.translation.simplifying:
- simplify.simplify_graph(graph)
+ simplify.simplify_graph(graph)
if self.config.translation.list_comprehension_operations:
simplify.detect_list_comprehension(graph)
if self.config.translation.verbose:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit