[pypy-svn] r12257 - pypy/dist/pypy/rpython

arigo at codespeak.net arigo at codespeak.net
Sat May 14 11:59:09 CEST 2005


Author: arigo
Date: Sat May 14 11:59:09 2005
New Revision: 12257

Modified:
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/typer.py
Log:
Slightly saner approach to building and registering list operations.


Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Sat May 14 11:59:09 2005
@@ -4,66 +4,61 @@
 from pypy.tool.template import compile_template
 
 
+class ListType:
+
+    def __init__(self, s_list):
+        assert isinstance(s_list, SomeList)
+        self.s_list = s_list
+        self.s_item = s_list.listdef.listitem.s_value
+        self.LIST = ForwardReference()
+        self.LISTPTR = GcPtr(self.LIST)
+        #self.ITEM = ... see below
+
+    def define(self, typer):
+        self.ITEM = typer.annotation2concretetype(self.s_item)
+        self.LIST.become(Struct("list",
+                                ("items", GcPtr(Array(('item', self.ITEM))))))
+
+        def getitem(l, i):
+            return l.items[i].item
+
+        typer['getitem', self.s_list, SomeInteger()] = (
+            getitem, self.LISTPTR, Signed, self.ITEM)
+
+    ##    def append(l, newitem):
+    ##        length = len(l.items)
+    ##        newitems = malloc(List_typ.items.TO, length+1)
+    ##        i = 0
+    ##        while i<length:
+    ##          newitems[i].item = l.items[i].item
+    ##          i += 1
+    ##        newitems[length].item = newitem
+    ##        l.items = newitems
+
+    ##    Registry['getattr', ...
+
+
+
 def substitute_newlist(typer, op):
+    # Make an implementation of newlist(x1,..,xn) which allocates
+    # a list with nbargs elements and initialize them.
     s_result = typer.annotator.binding(op.result)
-    LIST = getlisttype(typer, s_result)
-    T = getlistitemtype(typer, s_result)
-    n = len(op.args)
-    inputsignature = (T,) * n
-    try:
-        newlist = typer.newlistcache[LIST, n]
-    except KeyError:
-        # Make an implementation of newlist(x1,..,xn) which allocates
-        # a list with n elements and initialize them.
-        List_typ = LIST.TO
-
-        def template():
-            args = ', '.join(['arg%d' % i for i in range(n)])
-            yield     'def newlist(%s):' % args
-            yield     '    l = malloc(List_typ)'
-            yield     '    l.items = malloc(List_typ.items.TO, %d)' % n
-            for i in range(n):
-                yield '    l.items[%d].item = arg%d' % (i, i)
-            yield     '    return l'
-
-        newlist = compile_template(template(), 'newlist')
-        typer.newlistcache[LIST, n] = newlist
-    return typer.substitute_op(op, (newlist,) + inputsignature +  (LIST,))
-
-def getlisttype(typer, s_list):
-    assert isinstance(s_list, SomeList)
-    listdef = s_list.listdef
-    try:
-        return typer.listtypecache[listdef]
-    except KeyError:
-        List_typ = ForwardReference()
-        result = typer.listtypecache[listdef] = GcPtr(List_typ)
-        define_list(typer, s_list, List_typ)
-        return result
-
-def getlistitemtype(typer, s_list):
-    return typer.annotation2concretetype(s_list.listdef.listitem.s_value)
-
-
-def define_list(typer, s_list, List_typ):
-    T = getlistitemtype(typer, s_list)
-    List_typ.become(Struct("list",
-                           ("items", GcPtr(Array(('item',T))))))
-
-    def getitem(l, i):
-        return l.items[i].item
-
-    typer['getitem', s_list, SomeInteger()] = (
-        getitem, GcPtr(List_typ), Signed, T)
-
-##    def append(l, newitem):
-##        length = len(l.items)
-##        newitems = malloc(List_typ.items.TO, length+1)
-##        i = 0
-##        while i<length:
-##          newitems[i].item = l.items[i].item
-##          i += 1
-##        newitems[length].item = newitem
-##        l.items = newitems
-
-##    Registry['getattr', ...
+    listtype = typer.maketype(ListType, s_result)
+    LIST = listtype.LIST
+    nbargs = len(op.args)
+
+    def template():
+        args = ', '.join(['arg%d' % i for i in range(nbargs)])
+        yield     'def newlist(%s):' % args
+        yield     '    l = malloc(LIST)'
+        yield     '    l.items = malloc(LIST.items.TO, %d)' % nbargs
+        for i in range(nbargs):
+            yield '    l.items[%d].item = arg%d' % (i, i)
+        yield     '    return l'
+
+    newlist = compile_template(template(), 'newlist')
+
+    pattern = ('newlist',) + (listtype.s_item,)*nbargs
+    substitution = (newlist,) + (listtype.ITEM,)*nbargs + (listtype.LISTPTR,)
+    typer[pattern] = substitution
+    raise typer.Retry       # the new pattern should match now

Modified: pypy/dist/pypy/rpython/typer.py
==============================================================================
--- pypy/dist/pypy/rpython/typer.py	(original)
+++ pypy/dist/pypy/rpython/typer.py	Sat May 14 11:59:09 2005
@@ -3,13 +3,19 @@
 from pypy.annotation.model import *
 from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
 from pypy.translator.typer import Specializer, flatten_ops, TyperError
-from pypy.rpython.rlist import substitute_newlist, getlisttype
+from pypy.rpython.rlist import ListType, substitute_newlist
 
 
 PyObjPtr = GcPtr(PyObject)
 
+class Retry(Exception):
+    """Raised by substitute_*() after they have inserted new patterns
+    in the typer's registry.  This asks the typer to try again from
+    scratch to specialize the current operation."""
+
 
 class RPythonTyper(Specializer):
+    Retry = Retry
 
     def __init__(self, annotator):
         # initialization
@@ -17,6 +23,7 @@
                              typematches = [], specializationtable = [],
                              )
         self.registry = {}
+        self.typecache = {}
         SINT = SomeInteger()
         self['add', SINT, SINT] = 'int_add', Signed, Signed, Signed
         #self['add', UINT, UINT] = 'int_add', Unsigned, Unsigned, Unsigned
@@ -25,8 +32,6 @@
         self['simple_call', s_malloc, ...] = substitute_malloc
         
         # ____________________ lists ____________________
-        self.listtypecache = {}
-        self.newlistcache = {}
         self['newlist', ...] = substitute_newlist
 
         # ____________________ conversions ____________________
@@ -37,14 +42,24 @@
 
     def __setitem__(self, pattern, substitution):
         patternlist = self.registry.setdefault(pattern[0], [])
-        patternlist.append((pattern[1:], substitution))
+        # items inserted last have higher priority
+        patternlist.insert(0, (pattern[1:], substitution))
+
+    def maketype(self, cls, s_annotation):
+        try:
+            return self.typecache[cls, s_annotation]
+        except KeyError:
+            newtype = cls(s_annotation)
+            self.typecache[cls, s_annotation] = newtype
+            newtype.define(self)
+            return newtype
 
     def annotation2concretetype(self, s_value):
         try:
             return annotation_to_lltype(s_value)
         except ValueError:
             if isinstance(s_value, SomeList):
-                return getlisttype(self, s_value)
+                return self.maketype(ListType, s_value).LISTPTR
             return PyObjPtr
 
     def convertvar(self, v, concretetype):
@@ -125,7 +140,11 @@
                     break
             else:
                 # match!
-                return self.substitute_op(op, substitution)
+                try:
+                    return self.substitute_op(op, substitution)
+                except Retry:
+                    return self.specialized_op(op, bindings)
+
         # specialization not found
         argtypes = [self.defaultconcretetype] * len(op.args)
         return self.typed_op(op, argtypes, self.defaultconcretetype)



More information about the Pypy-commit mailing list