[pypy-svn] r5269 - in pypy/trunk/src/pypy: annotation objspace/flow translator translator/test

arigo at codespeak.net arigo at codespeak.net
Thu Jun 24 18:15:03 CEST 2004


Author: arigo
Date: Thu Jun 24 18:15:03 2004
New Revision: 5269

Modified:
   pypy/trunk/src/pypy/annotation/builtin.py
   pypy/trunk/src/pypy/annotation/model.py
   pypy/trunk/src/pypy/annotation/unaryop.py
   pypy/trunk/src/pypy/objspace/flow/flowcontext.py
   pypy/trunk/src/pypy/objspace/flow/objspace.py
   pypy/trunk/src/pypy/translator/annrpython.py
   pypy/trunk/src/pypy/translator/test/snippet.py
   pypy/trunk/src/pypy/translator/test/test_annrpython.py
   pypy/trunk/src/pypy/translator/translator.py
Log:
A lot of minor changes to better support annotating methods:

* Unbound methods are regarded as functions, for Parent.__init__().

* we can flow with constant arguments; used for the 'self' of
  constant bound method objects.  See test_global_instance().

* int() returns an integer (let's say).



Modified: pypy/trunk/src/pypy/annotation/builtin.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/builtin.py	(original)
+++ pypy/trunk/src/pypy/annotation/builtin.py	Thu Jun 24 18:15:03 2004
@@ -20,6 +20,12 @@
     else:
         return SomeObject()
 
+def builtin_int(s_obj):     # we can consider 'int' as a function
+    if isinstance(s_obj, SomeInteger):
+        return s_obj
+    else:
+        return SomeInteger()
+
 
 # collect all functions
 import __builtin__

Modified: pypy/trunk/src/pypy/annotation/model.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/model.py	(original)
+++ pypy/trunk/src/pypy/annotation/model.py	Thu Jun 24 18:15:03 2004
@@ -115,7 +115,8 @@
         self.s_self = s_self
 
 class SomeFunction(SomeObject):
-    "Stands for a Python function (or some function out of a list)."
+    """Stands for a Python function (or some function out of a list).
+    Alternatively, it can be a constant bound or unbound method."""
     knowntype = FunctionType
     def __init__(self, funcs):
         self.funcs = funcs   # set of functions that this one may be
@@ -153,7 +154,7 @@
         result = SomeBuiltin(BUILTIN_FUNCTIONS[x])
     elif isinstance(x, (type, ClassType)) and x.__module__ != '__builtin__':
         result = SomeClass(x)
-    elif isinstance(x, FunctionType):
+    elif isinstance(x, (FunctionType, MethodType)):
         result = SomeFunction({x: True})
     else:
         result = SomeObject()

Modified: pypy/trunk/src/pypy/annotation/unaryop.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/unaryop.py	(original)
+++ pypy/trunk/src/pypy/annotation/unaryop.py	Thu Jun 24 18:15:03 2004
@@ -2,6 +2,7 @@
 Unary operations on SomeValues.
 """
 
+from types import FunctionType
 from pypy.annotation.pairtype import pair
 from pypy.annotation.model import SomeObject, SomeInteger, SomeBool
 from pypy.annotation.model import SomeString, SomeList, SomeDict
@@ -148,6 +149,8 @@
     def classattribute(fun, classdef):   # function -> unbound method
         d = {}
         for func in fun.funcs:
+            assert isinstance(func, FunctionType), (
+                "%r should not be read out of class %r" % (func, classdef))
             d[func] = classdef
         return SomeMethod(d)
 

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	Thu Jun 24 18:15:03 2004
@@ -63,15 +63,17 @@
 
 class FlowExecutionContext(ExecutionContext):
 
-    def __init__(self, space, code, globals):
+    def __init__(self, space, code, globals, constargs={}):
         ExecutionContext.__init__(self, space)
         self.code = code
         self.w_globals = w_globals = space.wrap(globals)
         frame = self.create_frame()
         formalargcount = code.getformalargcount()
         dummy = UndefinedConstant()
-        arg_list = ([Variable() for i in range(formalargcount)] +
-                    [dummy] * (len(frame.fastlocals_w) - formalargcount))
+        arg_list = [Variable() for i in range(formalargcount)]
+        for position, value in constargs.items():
+            arg_list[position] = Constant(value)
+        arg_list += [dummy] * (len(frame.fastlocals_w) - formalargcount)
         frame.setfastscope(arg_list)
         self.joinpoints = {}
         for joinpoint in code.getjoinpoints():

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	Thu Jun 24 18:15:03 2004
@@ -67,12 +67,13 @@
         #print >> sys.stderr, '*** reraise', etype, evalue
         raise OperationError, OperationError(self.wrap(etype), self.wrap(evalue)), etb
 
-    def build_flow(self, func):
+    def build_flow(self, func, constargs={}):
         """
         """
         code = func.func_code
         code = PyCode()._from_code(code)
-        ec = flowcontext.FlowExecutionContext(self, code, func.func_globals)
+        ec = flowcontext.FlowExecutionContext(self, code, func.func_globals,
+                                              constargs)
         self.executioncontext = ec
         ec.build_flow()
         name = ec.graph.name
@@ -131,6 +132,8 @@
             op = issubclass
         elif name == 'id':
             op = id
+        elif name == 'getattr':
+            op = getattr
         else:
             if debug: print >> sys.stderr, "XXX missing operator:", name
 

Modified: pypy/trunk/src/pypy/translator/annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/annrpython.py	(original)
+++ pypy/trunk/src/pypy/translator/annrpython.py	Thu Jun 24 18:15:03 2004
@@ -35,6 +35,7 @@
             if self.translator is None:
                 from pypy.translator.translator import Translator
                 self.translator = Translator(func_or_flowgraph)
+                self.translator.annotator = self
             flowgraph = self.translator.getflowgraph(func_or_flowgraph)
         # make input arguments and set their type
         input_arg_types = list(input_arg_types)

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	Thu Jun 24 18:15:03 2004
@@ -328,6 +328,11 @@
     def __init__(self, n):
         self.a = n
 
+class WithMoreInit(WithInit):
+    def __init__(self, n, m):
+        WithInit.__init__(self, n)
+        self.b = m
+
 def simple_method(v=anytype):
     z = Z()
     z.my_attribute = v
@@ -337,6 +342,15 @@
     z = WithInit(v)
     return z.a
 
+def with_more_init(v=int, w=bool):
+    z = WithMoreInit(v, w)
+
+global_z = Z()
+global_z.my_attribute = 42
+
+def global_instance():
+    return global_z.my_method()
+
 
 def powerset(setsize=int):
     """Powerset

Modified: pypy/trunk/src/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/trunk/src/pypy/translator/test/test_annrpython.py	Thu Jun 24 18:15:03 2004
@@ -217,6 +217,26 @@
         # result should be an integer
         self.assertEquals(s.knowntype, int)
 
+    def test_with_more_init(self):
+        a = RPythonAnnotator()
+        s = a.build_types(snippet.with_more_init, [int, bool])
+        # the user classes should have the following attributes:
+        classes = a.bookkeeper.userclasses
+        # XXX on which class should the attribute 'a' appear?  We only
+        #     ever flow WithInit.__init__ with a self which is an instance
+        #     of WithMoreInit, so currently it appears on WithMoreInit.
+        self.assertEquals(classes[snippet.WithMoreInit].attrs.get('a'),
+                          annmodel.SomeInteger())
+        self.assertEquals(classes[snippet.WithMoreInit].attrs.get('b'),
+                          annmodel.SomeBool())
+
+    def test_global_instance(self):
+        a = RPythonAnnotator()
+        s = a.build_types(snippet.global_instance, [])
+        # currently this returns the constant 42.
+        # XXX not sure this is the best behavior...
+        self.assertEquals(s, annmodel.immutablevalue(42))
+
 def g(n):
     return [0,1,2,n]
 

Modified: pypy/trunk/src/pypy/translator/translator.py
==============================================================================
--- pypy/trunk/src/pypy/translator/translator.py	(original)
+++ pypy/trunk/src/pypy/translator/translator.py	Thu Jun 24 18:15:03 2004
@@ -43,8 +43,9 @@
 
 class Translator:
 
-    def __init__(self, func):
+    def __init__(self, func, verbose=False):
         self.entrypoint = func
+        self.verbose = verbose
         self.clear()
 
     def clear(self):
@@ -60,8 +61,17 @@
         try:
             graph = self.flowgraphs[func]
         except KeyError:
+            if self.verbose:
+                print 'getflowgraph:', func.__name__
+            im_func = getattr(func, 'im_func', func)
+            im_self = getattr(func, 'im_self', None)
+            if im_self is not None:    # bound method?
+                constargs = {0: im_self}
+            else:
+                constargs = {}
             space = FlowObjSpace()
-            graph = self.flowgraphs[func] = space.build_flow(func)
+            graph = self.flowgraphs[func] = space.build_flow(im_func,
+                                                             constargs)
             self.functions.append(func)
             try:
                 import inspect



More information about the Pypy-commit mailing list