[pypy-commit] pypy less-stringly-ops: replace SpaceOperators with subclasses of SpaceOperation

rlamy noreply at buildbot.pypy.org
Mon Aug 19 23:15:09 CEST 2013


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: less-stringly-ops
Changeset: r66235:5a1ff23cec22
Date: 2013-08-09 10:08 +0100
http://bitbucket.org/pypy/pypy/changeset/5a1ff23cec22/

Log:	replace SpaceOperators with subclasses of SpaceOperation

diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -451,11 +451,10 @@
         spaceop.offset = self.last_instr
         recorder.append(spaceop)
 
-    def do_op(self, operator, *args_w):
-        op = operator(*args_w)
+    def do_op(self, op):
         self.record(op)
-        if operator.canraise:
-            self.guessexception(operator.canraise)
+        if op.canraise:
+            self.guessexception(op.canraise)
         return op.result
 
     def guessexception(self, exceptions):
diff --git a/rpython/flowspace/objspace.py b/rpython/flowspace/objspace.py
--- a/rpython/flowspace/objspace.py
+++ b/rpython/flowspace/objspace.py
@@ -247,7 +247,7 @@
         if w_obj in self.not_really_const:
             const_w = self.not_really_const[w_obj]
             if w_name not in const_w:
-                return self.frame.do_op(op.getattr, w_obj, w_name)
+                return self.frame.do_op(op.getattr(w_obj, w_name))
         if w_obj.foldable() and w_name.foldable():
             obj, name = w_obj.value, w_name.value
             try:
@@ -261,7 +261,7 @@
                 return const(result)
             except WrapException:
                 pass
-        return self.frame.do_op(op.getattr, w_obj, w_name)
+        return self.frame.do_op(op.getattr(w_obj, w_name))
 
     def isinstance_w(self, w_obj, w_type):
         return self.is_true(self.isinstance(w_obj, w_type))
@@ -280,7 +280,7 @@
         if w_module in self.not_really_const:
             const_w = self.not_really_const[w_module]
             if w_name not in const_w:
-                return self.frame.do_op(op.getattr, w_module, w_name)
+                return self.frame.do_op(op.getattr(w_module, w_name))
         try:
             return const(getattr(w_module.value, w_name.value))
         except AttributeError:
@@ -355,14 +355,14 @@
                 raise FlowingError(self.frame, const(message))
         return const(value)
 
-def make_op(oper):
+def make_op(cls):
     def generic_operator(self, *args):
-        return oper.eval(self.frame, *args)
+        return cls(*args).eval(self.frame)
     return generic_operator
 
-for oper in op.__dict__.values():
-    if getattr(FlowObjSpace, oper.name, None) is None:
-        setattr(FlowObjSpace, oper.name, make_op(oper))
+for cls in op.__dict__.values():
+    if getattr(FlowObjSpace, cls.opname, None) is None:
+        setattr(FlowObjSpace, cls.opname, make_op(cls))
 
 
 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
@@ -7,7 +7,8 @@
 import __future__
 import operator
 from rpython.tool.sourcetools import compile2
-from rpython.flowspace.model import Constant, WrapException, const, Variable
+from rpython.flowspace.model import (Constant, WrapException, const, Variable,
+                                     SpaceOperation)
 from rpython.flowspace.specialcase import register_flow_sc
 
 class _OpHolder(object): pass
@@ -15,55 +16,50 @@
 
 func2op = {}
 
-class SpaceOperator(object):
+class HLOperation(SpaceOperation):
     pure = False
-    def __init__(self, name, arity, symbol, pyfunc, can_overflow=False):
-        self.name = name
-        self.arity = arity
-        self.symbol = symbol
-        self.pyfunc = pyfunc
-        self.can_overflow = can_overflow
-        self.canraise = []
+    def __init__(self, *args):
+        self.args = list(args)
+        self.result = Variable()
+        self.offset = -1
 
-    def make_sc(self):
+    @classmethod
+    def make_sc(cls):
         def sc_operator(space, args_w):
-            if len(args_w) != self.arity:
-                if self is op.pow and len(args_w) == 2:
+            if len(args_w) != cls.arity:
+                if cls is op.pow and len(args_w) == 2:
                     args_w = args_w + [Constant(None)]
-                elif self is op.getattr and len(args_w) == 3:
+                elif cls 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))
+                        cls.opname, cls.arity))
             # completely replace the call with the underlying
             # operation and its limited implicit exceptions semantic
-            return getattr(space, self.name)(*args_w)
+            return getattr(space, cls.opname)(*args_w)
         return sc_operator
 
-    def eval(self, frame, *args_w):
-        if len(args_w) != self.arity:
-            raise TypeError(self.name + " got the wrong number of arguments")
-        return frame.do_op(self, *args_w)
+    def eval(self, frame):
+        if len(self.args) != self.arity:
+            raise TypeError(self.opname + " got the wrong number of arguments")
+        return frame.do_op(self)
 
-    def __call__(self, *args_w):
-        return SpaceOperation(self.name, args_w, Variable())
-
-class PureOperator(SpaceOperator):
+class PureOperation(HLOperation):
     pure = True
 
-    def eval(self, frame, *args_w):
-        if len(args_w) != self.arity:
-            raise TypeError(self.name + " got the wrong number of arguments")
+    def eval(self, frame):
+        if len(self.args) != self.arity:
+            raise TypeError(self.opname + " 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]
+        if all(w_arg.foldable() for w_arg in self.args):
+            args = [w_arg.value for w_arg in self.args]
             # All arguments are constants: call the operator now
             try:
                 result = self.pyfunc(*args)
             except Exception as e:
                 from rpython.flowspace.flowcontext import FlowingError
                 msg = "%s%r always raises %s: %s" % (
-                    self.name, tuple(args), type(e), e)
+                    self.opname, tuple(args), type(e), e)
                 raise FlowingError(frame, msg)
             else:
                 # don't try to constant-fold operations giving a 'long'
@@ -73,7 +69,7 @@
                 if self.can_overflow and type(result) is long:
                     pass
                 # don't constant-fold getslice on lists, either
-                elif self.name == 'getslice' and type(result) is list:
+                elif self.opname == 'getslice' and type(result) is list:
                     pass
                 # otherwise, fine
                 else:
@@ -83,23 +79,26 @@
                         # type cannot sanely appear in flow graph,
                         # store operation with variable result instead
                         pass
-        return frame.do_op(self, *args_w)
+        return frame.do_op(self)
 
 
 def add_operator(name, arity, symbol, pyfunc=None, pure=False, ovf=False):
     operator_func = getattr(operator, name, None)
-    cls = PureOperator if pure else SpaceOperator
-    oper = cls(name, arity, symbol, pyfunc, can_overflow=ovf)
-    setattr(op, name, oper)
+    base_cls = PureOperation if pure else HLOperation
+    cls = type(name, (base_cls,), {'opname': name, 'arity': arity,
+                                   'can_overflow': ovf, 'canraise': []})
+    setattr(op, name, cls)
     if pyfunc is not None:
-        func2op[pyfunc] = oper
+        func2op[pyfunc] = cls
     if operator_func:
-        func2op[operator_func] = oper
-        if pyfunc is None:
-            oper.pyfunc = operator_func
+        func2op[operator_func] = cls
+    if pyfunc is not None:
+        cls.pyfunc = staticmethod(pyfunc)
+    elif operator_func is not None:
+        cls.pyfunc = staticmethod(operator_func)
     if ovf:
         from rpython.rlib.rarithmetic import ovfcheck
-        ovf_func = lambda *args: ovfcheck(oper.pyfunc(*args))
+        ovf_func = lambda *args: ovfcheck(cls.pyfunc(*args))
         add_operator(name + '_ovf', arity, symbol, pyfunc=ovf_func)
 
 # ____________________________________________________________
@@ -315,7 +314,7 @@
         oper = getattr(op, name)
         lis = oper.canraise
         if exc in lis:
-            raise ValueError, "your list is causing duplication!"
+            raise ValueError("your list is causing duplication!")
         lis.append(exc)
         assert exc in op_appendices
 


More information about the pypy-commit mailing list