[pypy-svn] r13508 - in pypy/dist/pypy/rpython: . test

arigo at codespeak.net arigo at codespeak.net
Fri Jun 17 02:19:04 CEST 2005


Author: arigo
Date: Fri Jun 17 02:19:02 2005
New Revision: 13508

Modified:
   pypy/dist/pypy/rpython/normalizecalls.py
   pypy/dist/pypy/rpython/rclass.py
   pypy/dist/pypy/rpython/rpbc.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rpbc.py
Log:
Fixed normalizecalls to know about classes.
Call the __init__ of classes when building instances.
Our first test that uses the LLInterpreter :-)



Modified: pypy/dist/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/normalizecalls.py	Fri Jun 17 02:19:02 2005
@@ -30,6 +30,19 @@
                 argcount = pattern[0]
                 pattern = (argcount+1,) + pattern[1:]
                 func_family.patterns[pattern] = True
+    # for classes that appear in families, unify their __init__ as well
+    for family in call_families.infos():
+        prevkey = None
+        for _, klass in family.objects:
+            if isinstance(klass, (type, types.ClassType)):
+                try:
+                    initfunc = klass.__init__.im_func
+                except AttributeError:
+                    continue
+                if prevkey is None:
+                    prevkey = (None, initfunc)
+                else:
+                    call_families.union((None, initfunc), prevkey)
     # find the most general signature of each family
     for family in call_families.infos():
         # collect functions in this family, ignoring:

Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py	(original)
+++ pypy/dist/pypy/rpython/rclass.py	Fri Jun 17 02:19:02 2005
@@ -512,6 +512,13 @@
     rinstance = getinstancerepr(hop.rtyper, classdef)
     return rinstance.new_instance(hop.llops)
 
+def instance_annotation_for_cls(rtyper, cls):
+    try:
+        classdef = rtyper.annotator.getuserclasses()[cls]
+    except KeyError:
+        raise TyperError("no classdef: %r" % (cls,))
+    return annmodel.SomeInstance(classdef)
+
 # ____________________________________________________________
 #
 #  Low-level implementation of operations on classes and instances

Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Fri Jun 17 02:19:02 2005
@@ -2,10 +2,12 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.annotation.classdef import isclassdef
+from pypy.objspace.flow.model import Constant
 from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct
 from pypy.rpython.lltype import Ptr, malloc, nullptr
 from pypy.rpython.rmodel import Repr, TyperError
 from pypy.rpython import rclass
+from pypy.rpython.rtyper import HighLevelOp
 
 
 class __extend__(annmodel.SomePBC):
@@ -316,5 +318,25 @@
 ##                    s_pbc.prebuiltinstances,))
 
     def rtype_simple_call(self, hop):
-        return rclass.rtype_new_instance(self.s_pbc.const, hop)
-        # XXX call __init__ somewhere
+        klass = self.s_pbc.const
+        v_instance = rclass.rtype_new_instance(klass, hop)
+        try:
+            initfunc = klass.__init__.im_func
+        except AttributeError:
+            assert hop.nb_args == 1, ("arguments passed to __init__, "
+                                      "but no __init__!")
+        else:
+            if initfunc == Exception.__init__.im_func:
+                return v_instance    # ignore __init__ and arguments completely
+            s_instance = rclass.instance_annotation_for_cls(self.rtyper, klass)
+            s_init = annmodel.SomePBC({initfunc: True})
+            hop2 = hop.copy()
+            hop2.r_s_popfirstarg()   # discard the class pointer argument
+            hop2.v_s_insertfirstarg(v_instance, s_instance)  # (instance, *args)
+            c = Constant(initfunc)
+            hop2.v_s_insertfirstarg(c, s_init)   # (initfunc, instance, *args)
+            hop2.s_result = annmodel.SomePBC({None: True})
+            hop2.r_result = self.rtyper.getrepr(hop2.s_result)
+            r_init = self.rtyper.getrepr(s_init)
+            r_init.rtype_simple_call(hop2)
+        return v_instance

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Fri Jun 17 02:19:02 2005
@@ -366,14 +366,14 @@
 # ____________________________________________________________
 
 
-class HighLevelOp:
-    nb_popped = 0
+class HighLevelOp(object):
 
     def __init__(self, rtyper, spaceop, exceptionlinks, llops):
         self.rtyper   = rtyper
         self.spaceop  = spaceop
         self.nb_args  = len(spaceop.args)
         self.llops    = llops
+        self.args_v   = list(spaceop.args)
         self.args_s   = [rtyper.binding(a) for a in spaceop.args]
         self.s_result = rtyper.binding(spaceop.result)
         self.args_r   = [rtyper.getrepr(s_a) for s_a in self.args_s]
@@ -381,6 +381,14 @@
         rtyper.call_all_setups()  # compute ForwardReferences now
         self.exceptionlinks = exceptionlinks
 
+    def copy(self):
+        result = HighLevelOp.__new__(HighLevelOp)
+        for key, value in self.__dict__.items():
+            if type(value) is list:     # grunt
+                value = value[:]
+            setattr(result, key, value)
+        return result
+
     def inputarg(self, converted_to, arg):
         """Returns the arg'th input argument of the current operation,
         as a Variable or Constant converted to the requested type.
@@ -389,7 +397,7 @@
         """
         if not isinstance(converted_to, Repr):
             converted_to = self.rtyper.primitive_to_repr[converted_to]
-        v = self.spaceop.args[self.nb_popped + arg]
+        v = self.args_v[arg]
         if isinstance(v, Constant):
             return inputconst(converted_to, v.value)
         assert hasattr(v, 'concretetype')
@@ -405,8 +413,8 @@
 
     def inputargs(self, *converted_to):
         assert len(converted_to) == self.nb_args, (
-            "operation argument count mismatch: '%s' has %d+%d arguments" % (
-            self.spaceop.opname, self.nb_popped, self.nb_args))
+            "operation argument count mismatch: '%s' has %d arguments" % (
+            self.spaceop.opname, self.nb_args))
         vars = []
         for i in range(len(converted_to)):
             vars.append(self.inputarg(converted_to[i], i))
@@ -420,10 +428,17 @@
 
     def r_s_popfirstarg(self):
         "Return and discard the first argument."
-        self.nb_popped += 1
         self.nb_args -= 1
+        self.args_v.pop(0)
         return self.args_r.pop(0), self.args_s.pop(0)
 
+    def v_s_insertfirstarg(self, v_newfirstarg, s_newfirstarg):
+        r_newfirstarg = self.rtyper.getrepr(s_newfirstarg)
+        self.args_v.insert(0, v_newfirstarg)
+        self.args_r.insert(0, r_newfirstarg)
+        self.args_s.insert(0, s_newfirstarg)
+        self.nb_args += 1
+
     def has_implicit_exception(self, exc_cls):
         for link in self.exceptionlinks:
             if issubclass(exc_cls, link.exitcase):

Modified: pypy/dist/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rpbc.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rpbc.py	Fri Jun 17 02:19:02 2005
@@ -1,6 +1,7 @@
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
 from pypy.rpython.rtyper import RPythonTyper
+from pypy.rpython.test.test_interp import interpret
 
 
 def rtype(fn, argtypes=[]):
@@ -59,6 +60,17 @@
     rtype(f, [int, int])
 
 
+class MyBaseWithInit:
+    def __init__(self, a):
+        self.a1 = a
+
+def test_class_init():
+    def f(a):
+        instance = MyBaseWithInit(a)
+        return instance.a1
+    assert interpret(f, [5]) == 5
+
+
 class Freezing:
     def _freeze_(self):
         return True



More information about the Pypy-commit mailing list