Commits

Ronan Lamy committed 3a5b76c

Move implementation of FlowObjSpace.getattr() to op.getatttr

  • Participants
  • Parent commits d0d7f77
  • Branches less-stringly-ops

Comments (0)

Files changed (2)

File rpython/flowspace/objspace.py

 from rpython.flowspace.model import (Constant, Variable, WrapException,
     UnwrapException, checkgraph, const, FSException)
 from rpython.flowspace.bytecode import HostCode
-from rpython.flowspace.operation import op
+from rpython.flowspace.operation import op, NOT_REALLY_CONST
 from rpython.flowspace.flowcontext import (FlowSpaceFrame, fixeggblocks,
     FlowingError)
 from rpython.flowspace.generator import (tweak_generator_graph,
 from rpython.rlib import rstackovf
 
 
-# the following gives us easy access to declare more for applications:
-NOT_REALLY_CONST = {
-    Constant(sys): {
-        Constant('maxint'): True,
-        Constant('maxunicode'): True,
-        Constant('api_version'): True,
-        Constant('exit'): True,
-        Constant('exc_info'): True,
-        Constant('getrefcount'): True,
-        Constant('getdefaultencoding'): True,
-        # this is an incomplete list of true constants.
-        # if we add much more, a dedicated class
-        # might be considered for special objects.
-        }
-    }
-
 # built-ins that can always raise exceptions
 builtins_exceptions = {
     int: [ValueError],
     # during flow graph construction
     w_NameError = 'NameError'
     w_UnboundLocalError = 'UnboundLocalError'
-
     specialcases = SPECIAL_CASES
-    # objects which should keep their SomeObjectness
-    not_really_const = NOT_REALLY_CONST
 
     def build_flow(self, func):
         return build_flow(func, self)
         return const(not self.frame.guessbool(self.bool(w_obj)))
 
 
-    def getattr(self, w_obj, w_name):
-        # handling special things like sys
-        # unfortunately this will never vanish with a unique import logic :-(
-        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))
-        if w_obj.foldable() and w_name.foldable():
-            obj, name = w_obj.value, w_name.value
-            try:
-                result = getattr(obj, name)
-            except Exception, e:
-                etype = e.__class__
-                msg = "getattr(%s, %s) always raises %s: %s" % (
-                    obj, name, etype, e)
-                raise FlowingError(msg)
-            try:
-                return const(result)
-            except WrapException:
-                pass
-        return self.frame.do_op(op.getattr(w_obj, w_name))
-
     def import_name(self, name, glob=None, loc=None, frm=None, level=-1):
         try:
             mod = __import__(name, glob, loc, frm, level)
         assert isinstance(w_module, Constant)
         assert isinstance(w_name, Constant)
         # handle sys
-        if w_module in self.not_really_const:
-            const_w = self.not_really_const[w_module]
+        if w_module in NOT_REALLY_CONST:
+            const_w = NOT_REALLY_CONST[w_module]
             if w_name not in const_w:
                 return self.frame.do_op(op.getattr(w_module, w_name))
         try:

File rpython/flowspace/operation.py

 import __builtin__
 import __future__
 import operator
+import sys
 from rpython.rlib.unroll import unrolling_iterable, _unroller
 from rpython.tool.sourcetools import compile2
 from rpython.flowspace.model import (Constant, WrapException, const, Variable,
                                      SpaceOperation)
 from rpython.flowspace.specialcase import register_flow_sc
 
+NOT_REALLY_CONST = {
+    Constant(sys): {
+        Constant('maxint'): True,
+        Constant('maxunicode'): True,
+        Constant('api_version'): True,
+        Constant('exit'): True,
+        Constant('exc_info'): True,
+        Constant('getrefcount'): True,
+        Constant('getdefaultencoding'): True,
+        # this is an incomplete list of true constants.
+        # if we add much more, a dedicated class
+        # might be considered for special objects.
+        }
+    }
+
+
 class _OpHolder(object): pass
 op = _OpHolder()
 
 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)
         return w_item
 op.next = Next
 
+class GetAttr(HLOperation):
+    opname = 'getattr'
+    arity = 2
+    can_overflow = False
+    canraise = []
+    pyfunc = staticmethod(getattr)
+
+    def constfold(self):
+        w_obj, w_name = self.args
+        # handling special things like sys
+        if (w_obj in NOT_REALLY_CONST and
+                w_name not in NOT_REALLY_CONST[w_obj]):
+            return
+        if w_obj.foldable() and w_name.foldable():
+            obj, name = w_obj.value, w_name.value
+            try:
+                result = getattr(obj, name)
+            except Exception as e:
+                from rpython.flowspace.flowcontext import FlowingError
+                etype = e.__class__
+                msg = "getattr(%s, %s) always raises %s: %s" % (
+                    obj, name, etype, e)
+                raise FlowingError(msg)
+            try:
+                return const(result)
+            except WrapException:
+                pass
+op.getattr = GetAttr
+
+
 
 # Other functions that get directly translated to SpaceOperators
 func2op[type] = op.type
 func2op[operator.truth] = op.bool
 func2op[__builtin__.iter] = op.iter
-if hasattr(__builtin__, 'next'):
-    func2op[__builtin__.next] = op.next
+func2op[getattr] = op.getattr
+func2op[__builtin__.next] = op.next
 
 for fn, oper in func2op.items():
     register_flow_sc(fn)(oper.make_sc())