[pypy-svn] rev 2489 - in pypy/trunk/src/pypy: annotation annotation/testtranslator translator/test

arigo at codespeak.net arigo at codespeak.net
Thu Dec 18 13:16:54 CET 2003


Author: arigo
Date: Thu Dec 18 13:16:53 2003
New Revision: 2489

Removed:
   pypy/trunk/src/pypy/translator/annheap.py
   pypy/trunk/src/pypy/translator/annotation.py
   pypy/trunk/src/pypy/translator/test/test_annheap.py
   pypy/trunk/src/pypy/translator/test/test_annotation.py
Modified:
   pypy/trunk/src/pypy/annotation/annset.py
   pypy/trunk/src/pypy/annotation/model.py
   pypy/trunk/src/pypy/annotation/test/test_annset.py
   pypy/trunk/src/pypy/translator/annrpython.py
   pypy/trunk/src/pypy/translator/translator.py
Log:
Started to port translator to the new annotations.
Currently only translator.py can be imported, not gencl nor genpyrex.


Modified: pypy/trunk/src/pypy/annotation/annset.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/annset.py	(original)
+++ pypy/trunk/src/pypy/annotation/annset.py	Thu Dec 18 13:16:53 2003
@@ -6,6 +6,10 @@
 QUERYARG = QueryArgument()
 
 
+class IDontKnow(Exception):
+    pass
+
+
 class AnnotationSet:
     """An annotation set is a (large) family of Annotations."""
 
@@ -109,15 +113,6 @@
         """ list all matching annotations."""
         return list(self._annmatches(checkann))
 
-    def queryconstant(self, cell):
-        "Return the list of all 'x' such that ANN.constant(x)[cell] is set."
-        cell = self.normalized(cell)
-        result = []
-        for ann in self.annlist:
-            if isinstance(ann.predicate, ConstPredicate) and ann.args[0] is cell:
-                result.append(ann.predicate.value)
-        return result
-
     def record(self, recfunc, *args):
         """ invoke the given 'recording' function by passing it a new 
         Recorder instance and letting it use its modification API.  This API will
@@ -232,6 +227,28 @@
         else:
             return None
 
+    def get_del(self, *querylist):
+        """Like get() but kills the matching annotation."""
+        resultlist = list(self.match(*querylist))
+        assert len(resultlist) <= 1, "Confusing annotations..."
+        if resultlist:
+            matchanns, matchvalue = resultlist[0]
+            self.kill(*matchanns)
+            return matchvalue
+        else:
+            return None
+
+    def getconstant(self, cell):
+        """If cell is a constant, return its value; otherwise, raise IDontKnow.
+        Also accepts a None for convenience."""
+        if not cell:
+            raise IDontKnow
+        cell = self.normalized(cell)
+        for ann in self.annlist:
+            if isinstance(ann.predicate, ConstPredicate) and ann.args[0] is cell:
+                return ann.predicate.value
+        raise IDontKnow, cell
+
     def set(self, ann):
         """Insert the annotation into the AnnotationSet."""
         self.normalizeann(ann)
@@ -260,6 +277,12 @@
         if knowntype in immutable_types:
             self.set(ANN.immutable[someval])
 
+    def copytype(self, oldcell, newcell):
+        for typecell in self.query(ANN.type[oldcell, QUERYARG]):
+            self.set(ANN.type[newcell, typecell])
+        if self.findfirst(ANN.immutable[oldcell]):
+            self.set(ANN.immutable[newcell])
+
     def newconstant(self, value):
         cell = SomeValue()
         self.set(ANN.constant(value)[cell])

Modified: pypy/trunk/src/pypy/annotation/model.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/model.py	(original)
+++ pypy/trunk/src/pypy/annotation/model.py	Thu Dec 18 13:16:53 2003
@@ -30,6 +30,8 @@
 
 class ANN:
     add = Predicate('add', 3)
+    len = Predicate('len', 2)
+    getitem = Predicate('getitem', 3)
     neg = Predicate('neg', 2)
     constant = ConstPredicate
     type = Predicate('type', 2)
@@ -85,6 +87,7 @@
     tuple: 'tuple',
     str: 'str',
     bool: 'bool',
+    slice: 'slice',
     types.FunctionType: 'function',
     }
 

Modified: pypy/trunk/src/pypy/annotation/test/test_annset.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/test/test_annset.py	(original)
+++ pypy/trunk/src/pypy/annotation/test/test_annset.py	Thu Dec 18 13:16:53 2003
@@ -3,7 +3,7 @@
 from pypy.tool import test
 
 from pypy.annotation.model import ANN, SomeValue, blackholevalue
-from pypy.annotation.annset import AnnotationSet, QUERYARG
+from pypy.annotation.annset import AnnotationSet, QUERYARG, IDontKnow
 
 
 c1,c2,c3,c4 = SomeValue(), SomeValue(), SomeValue(), SomeValue()
@@ -89,15 +89,13 @@
         c = a.newconstant(42)
         self.assertSameSet(a, [ANN.constant(42)[c]])
 
-    def test_queryconstant(self):
+    def test_getconstant(self):
         lst = [
             ANN.constant(42)[c1],
         ]
         a = AnnotationSet(lst)
-        vlist = a.queryconstant(c1)
-        self.assertEquals(vlist, [42])
-        vlist = a.queryconstant(c2)
-        self.assertEquals(vlist, [])
+        self.assertEquals(a.getconstant(c1), 42)
+        self.assertRaises(IDontKnow, a.getconstant, c2)
 
     def test_query_blackholevalue(self):
         lst = [
@@ -301,6 +299,17 @@
         a.delete(ANN.add[c1, c3, ...])
         self.assertSameSet(a, lst[1:])
 
+    def test_get_del(self):
+        lst = [
+            ANN.add[c1, c3, c2],
+            ANN.type[c1, c4],
+            ANN.constant(int)[c4],
+        ]
+        a = AnnotationSet(lst)
+        c = a.get_del(ANN.add[c1, c3, QUERYARG])
+        self.assertSameCells(a, c, c2)
+        self.assertSameSet(a, lst[1:])
+
 
 if __name__ == '__main__':
     test.main()

Deleted: /pypy/trunk/src/pypy/translator/annheap.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/annheap.py	Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,212 +0,0 @@
-from __future__ import generators
-import types
-from annotation import Annotation, XCell, XConstant, nothingyet
-
-
-class AnnotationHeap:
-    """An annotation heap is a (large) family of Annotations."""
-
-    # XXX STORED AS A PLAIN LIST, THE COMPLEXITY IS PLAINLY WRONG
-
-    def __init__(self, annlist=[]):
-        self.annlist = list(annlist)    # List of annotations
-
-    def dump(self):     # debugging
-        for ann in self.enumerate():
-            print ann
-
-    def enumerate(self):
-        """Enumerates all annotations in the heap."""
-        return iter(self.annlist)
-
-    __iter__ = enumerate
-
-    def simplify(self, kill=[]):
-        """Kill annotations in the list, and recursively all the annotations
-        that depend on them, and simplify the resulting heap to remove
-        duplicates."""
-        # temporarykey() returns a tuple with all the information about
-        # the annotation; equal temporarykey() means equal annotations.
-        # Such keys are temporary because making new XCells shared can
-        # change the temporarykey(), but this doesn't occur during
-        # one call to simplify().
-        
-        allkeys = {}   # map temporarykeys to Annotation instances
-        for ann in self.annlist:
-            key = ann.temporarykey()
-            if key in allkeys:  # duplicate?
-                previous = allkeys[key]
-                previous.forward_deps += ann.forward_deps   # merge
-            else:
-                allkeys[key] = ann
-
-        killkeys = {}  # set of temporarykeys of annotations to remove
-        for ann in kill:
-            killkeys[ann.temporarykey()] = True
-
-        pending = killkeys.keys()
-        for key in pending:
-            if key in allkeys:
-                ann = allkeys[key]
-                del allkeys[key]    # remove annotations from the dict
-                for dep in ann.forward_deps:   # propagate dependencies
-                    depkey = dep.temporarykey()
-                    if depkey not in killkeys:
-                        killkeys[depkey] = True
-                        pending.append(depkey)
-
-        self.annlist = allkeys.values()
-
-    def merge(self, oldcell, newcell):
-        """Update the heap to account for the merging of oldcell and newcell.
-        Return the merged cell."""
-        if newcell is nothingyet or newcell == oldcell:
-            return oldcell
-        elif oldcell is nothingyet:
-            return newcell
-        else:
-            # any annotation or "constantness" about oldcell that must be killed?
-            deleting = isinstance(oldcell, XConstant)
-            # find the annotations common to oldcell and newcell
-            common = []
-            for ann in self.annlist:
-                if oldcell in ann.args or oldcell == ann.result:
-                    test1 = rename(ann, oldcell, newcell)
-                    test2 = rename(ann, newcell, oldcell)  # may equal 'ann'
-                    if test1 in self.annlist and test2 in self.annlist:
-                        common.append(test1)
-                    else:
-                        deleting = True
-            # the involved objects are immutable if we have both
-            # 'immutable() -> oldcell' and 'immutable() -> newcell'
-            if Annotation('immutable', [], newcell) in common:
-                # for immutable objects we can create a new cell if necessary
-                if not deleting:
-                    return oldcell  # nothing must be removed from oldcell
-                else:
-                    resultcell = XCell()  # invent a new cell
-                    for ann in common:
-                        self.annlist.append(rename(ann, newcell, resultcell))
-                    return resultcell
-            else:
-                if Annotation('immutable', [], oldcell) in self.annlist:
-                    pass # old was immutable, don't touch it
-                elif Annotation('immutable', [], newcell) in self.annlist:
-                    # new is immutable, old was not, inverse the roles
-                    oldcell, newcell = newcell, oldcell
-                else:
-                    # two mutable objects: we identify oldcell and newcell
-                    newcell.share(oldcell)
-                # only keep the common annotations by listing all annotations
-                # to remove, which are the ones that talk about newcell but
-                # are not in 'common'.
-                deleting = []
-                for ann in self.annlist:
-                    if newcell in ann.args or newcell == ann.result:
-                        if ann not in common:
-                            deleting.append(ann)
-                # apply changes
-                self.simplify(kill=deleting)
-                return newcell
-
-
-def rename(ann, oldcell, newcell):
-    "Make a copy of 'ann' in which 'oldcell' has been replaced by 'newcell'."
-    args = []
-    for a in ann.args:
-        if a == oldcell:
-            a = newcell
-        args.append(a)
-    a = ann.result
-    if a == oldcell:
-        a = newcell
-    return Annotation(ann.opname, args, a)
-
-
-class Transaction:
-    """A transaction contains methods to look for annotations in the
-    AnnotationHeap and create new annotations accordingly.  Each
-    Transaction instance records which Annotations were needed, which
-    allows dependencies to be tracked."""
-
-    def __init__(self, heap):
-        self.heap = heap
-        self.using_annotations = []  # annotations that we have used
-
-    def _list_annotations(self, opname, args):
-        # patch(arglist) -> arglist with None plugged where
-        #                   there is a None in the input 'args'
-        def patch(arglist):
-            return arglist
-        for i in range(len(args)):
-            if args[i] is None:
-                def patch(arglist, prevpatch=patch, i=i):
-                    arglist = prevpatch(arglist)[:]
-                    arglist[i] = None
-                    return arglist
-        
-        matchann = []
-        for ann in self.heap.annlist:
-            if ann.opname == opname and patch(ann.args) == args:
-                matchann.append(ann)
-        return matchann
-
-    def get(self, opname, args):
-        """Return the Cell with the annotation 'opname(args) -> Cell',
-        or None if there is no such annotation or several different ones.
-        Hack to generalize: a None in the args matches anything."""
-        matchann = self._list_annotations(opname, args)
-        if not matchann:
-            return None
-        else:
-            result = matchann[0].result
-            for ann in matchann[1:]:
-                if result != ann.result:
-                    return None   # conflicting results
-            for ann in matchann:
-                self.using(ann)
-            return result
-
-    def delete(self, opname, args):
-        """Kill the annotations 'opname(args) -> *'."""
-        matchann = self._list_annotations(opname, args)
-        self.heap.simplify(kill=matchann)
-
-    def set(self, opname, args, result):
-        """Put a new annotation into the AnnotationHeap."""
-        ann = Annotation(opname, args, result)
-        for prev in self.using_annotations:
-            prev.forward_deps.append(ann)
-        self.heap.annlist.append(ann)
-
-    def get_type(self, cell):
-        """Get the type of 'cell', as specified by the annotations, or None.
-        Returns None if cell is None."""
-        if cell is None:
-            return None
-        assert isinstance(cell, XCell)
-        c = self.get('type', [cell])
-        if isinstance(c, XConstant):
-            return c.value
-        else:
-            return None
-
-    def set_type(self, cell, type):
-        """Register an annotation describing the type of the object 'cell'."""
-        self.set('type', [cell], XConstant(type))
-        if type in immutable_types:
-            self.set('immutable', [], cell)
-
-    def using(self, ann):
-        """Mark 'ann' as used in this transaction."""
-        self.using_annotations.append(ann)
-
-
-immutable_types = {
-    int: True,
-    long: True,
-    tuple: True,
-    str: True,
-    bool: True,
-    types.FunctionType: True,
-    }

Deleted: /pypy/trunk/src/pypy/translator/annotation.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/annotation.py	Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,137 +0,0 @@
-import weakref
-
-
-class Annotation:
-    """An Annotation asserts something about heap objects represented
-    by XCell instances."""
-    
-    # Note that this is very much like a SpaceOperation, but we keep
-    # them separate because they have different purposes.
-
-    # Attention, handle Annotations with care!  Two Annotations that
-    # were initially different could become equal when XCells become
-    # shared.  This is the reason why Annotations are not hashable.
-
-    def __init__(self, opname, args, result):
-        self.opname = opname      # operation name
-        self.args   = list(args)  # list of XCells
-        self.result = result      # an XCell
-        self.forward_deps = []    # annotations that depend on this one
-        # catch bugs involving confusion between Variables/Constants
-        # and XCells/XConstants
-        for cell in args + [result]:
-            assert isinstance(cell, XCell)
-
-    def __eq__(self, other):
-        return (self.__class__ is other.__class__ and 
-                self.opname == other.opname and
-                self.args == other.args and
-                self.result == other.result)
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        return "%s(%s) -> %s" % (self.opname, ", ".join(map(repr, self.args)),
-                                 self.result)
-
-    def temporarykey(self):
-        lst = [self.opname, self.result.temporarykey()]
-        lst += [arg.temporarykey() for arg in self.args]
-        return tuple(lst)
-
-def debugname(xcell, name=None, _seen = {}):
-    """ return a simple name for an xcell. """
-    try:
-        return _seen[id(xcell)]
-    except KeyError:
-        if name is None:
-            name = "X%d" % len(_seen)
-        _seen[id(xcell)] = name
-        return name
-
-class XCell:
-    """A placeholder for a heap object contained in an AnnotationHeap.
-    It represents an object that will actually appear at run-time in the heap.
-    XCells are the arguments and return value of Annotations."""
-
-    # Multiple XCells can be "shared"; a group of shared cells
-    # act essentially like a single cell (they become all equal).
-    
-    def __init__(self):
-        self.shared = []    # list of weakrefs to XCells
-                            # defining a group of shared cells.
-
-    def __repr__(self):
-        names = [debugname(cell) for cell in self.cellsingroup()]
-        names.sort()
-        return '=='.join(names)
-
-    def __eq__(self, other):
-        "Two sharing cells are equal."
-        return isinstance(other, XCell) and self.is_shared(other)
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def temporarykey(self):
-        ids = [id(cell) for cell in self.cellsingroup()]
-        return min(ids)
-
-    def cellsingroup(self):
-        if self.shared:
-            l = [s() for s in self.shared]
-            assert self in l
-            return [c for c in l if c is not None]
-        else:
-            return [self]
-
-    def getsharelist(self):
-        if not self.shared:
-            self.shared = [weakref.ref(self)]
-        return self.shared
-
-    def is_shared(self, other):
-        "Test if two cells are shared."
-        return self.shared is other.shared
-
-    def share(self, other):
-        "Make two cells shared."
-        if not self.is_shared(other):
-            lst1 = self.getsharelist()
-            lst2 = other.getsharelist()
-            for s in lst2:
-                c = s()
-                if c is not None:
-                    c.shared = lst1
-                    lst1.append(s)
-
-class XConstant(XCell):
-    """A fully determined XCell.  For immutable constants."""
-
-    def __init__(self, value):
-        XCell.__init__(self)
-        self.value = value
-
-    def __eq__(self, other):
-        "Two constants with the same value are equal."
-        return (isinstance(other, XConstant) and self.value == other.value
-                or XCell.__eq__(self, other))
-
-    def __repr__(self):
-        if self.shared:
-            return 'UNEXPECTEDLY SHARED %r' % XCell.__repr__(self)
-        else:
-            return 'XConstant %r' % self.value
-
-
-# The more annotations about an XCell, the least general
-# it is.  Extreme case: *all* possible annotations stand for an
-# object that cannot exist (e.g. the return value of a function
-# that never returns or we didn't see return so far).
-# This is specified by using nothingyet instead of a real XCell().
-# Conversely, *no* annotation stands for any object.
-
-nothingyet = XCell()
-debugname(nothingyet, 'nothingyet')
-

Modified: pypy/trunk/src/pypy/translator/annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/annrpython.py	(original)
+++ pypy/trunk/src/pypy/translator/annrpython.py	Thu Dec 18 13:16:53 2003
@@ -1,9 +1,9 @@
 from __future__ import generators
 
 from types import FunctionType
-from pypy.translator.annheap import AnnotationHeap, Transaction
-from pypy.translator.annotation import XCell, XConstant, nothingyet
-from pypy.translator.annotation import Annotation
+from pypy.annotation.model import SomeValue, ANN, blackholevalue
+from pypy.annotation.model import intvalue, boolvalue, slicevalue
+from pypy.annotation.annset import AnnotationSet, QUERYARG, IDontKnow
 from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant
 from pypy.objspace.flow.model import SpaceOperation
 
@@ -17,18 +17,13 @@
     See description in doc/transation/annotation.txt."""
 
     def __init__(self, translator=None):
-        self.heap = AnnotationHeap()
-        self.pendingblocks = []  # list of (block, list-of-XCells)
+        self.heap = AnnotationSet()
+        self.pendingblocks = []  # list of (block, list-of-SomeValues-args)
         self.delayedblocks = []  # list of blocked blocks
-        self.bindings = {}       # map Variables/Constants to XCells/XConstants
+        self.bindings = self.heap.getbindings()  # map Variables/Constants
+                                                 # to SomeValues
         self.annotated = {}      # set of blocks already seen
         self.translator = translator
-        # build default annotations
-        t = self.transaction()
-        self.any_immutable = XCell()
-        t.set('immutable', [], self.any_immutable)
-        self.any_int = XCell()
-        t.set_type(self.any_int, int)
 
 
     #___ convenience high-level interface __________________
@@ -36,10 +31,10 @@
     def build_types(self, flowgraph, input_arg_types):
         """Recursively build annotations about the specific entry point."""
         # make input arguments and set their type
-        inputcells = [XCell() for arg in flowgraph.getargs()]
-        t = self.transaction()
+        inputcells = [SomeValue() for arg in flowgraph.getargs()]
         for cell, arg_type in zip(inputcells, input_arg_types):
-            t.set_type(cell, arg_type)
+            self.heap.settype(cell, arg_type)
+        
         # register the entry point
         self.addpendingblock(flowgraph.startblock, inputcells)
         # recursively proceed until no more pending block is left
@@ -52,11 +47,6 @@
         """Register an entry point into block with the given input cells."""
         self.pendingblocks.append((block, cells))
 
-    def transaction(self):
-        """Start a Transaction.  Each new Annotation is marked as depending
-        on the Annotations queried for during the same Transation."""
-        return Transaction(self.heap)
-
     def complete(self):
         """Process pending blocks until none is left."""
         while self.pendingblocks:
@@ -70,28 +60,21 @@
                                  len(delayed))
 
     def binding(self, arg):
-        "XCell or XConstant corresponding to the given Variable or Constant."
+        "Gives the SomeValue corresponding to the given Variable or Constant."
         try:
             return self.bindings[arg]
         except KeyError:
             if not isinstance(arg, Constant):
                 raise   # propagate missing bindings for Variables
             if isinstance(arg, UndefinedConstant):
-                result = nothingyet  # undefined local variables
+                result = blackholevalue  # undefined local variables
             else:
-                result = XConstant(arg.value)
-                self.consider_const(result, arg)
+                result = self.consider_const(arg.value)
             self.bindings[arg] = result
             return result
 
-    def bindnew(self, arg):
-        "Force the creation of a new binding for the given Variable."
-        assert isinstance(arg, Variable)
-        self.bindings[arg] = result = XCell()
-        return result
-
     def constant(self, value):
-        "Turn a value into an XConstant with the proper annotations."
+        "Turn a value into a SomeValue with the proper annotations."
         return self.binding(Constant(value))
 
 
@@ -104,20 +87,22 @@
     def reverse_binding(self, known_variables, cell):
         """This is a hack."""
         # In simplify_calls, when we are trying to create the new
-        # SpaceOperation, all we have are XCells.  But SpaceOperations take
-        # Variables, not XCells.  Trouble is, we don't always have a Variable
-        # that just happens to be bound to the given XCells.  A typical
-        # example would be if the tuple of arguments was created from another
-        # basic block or even another function.  Well I guess there is no
-        # clean solution.
-        if isinstance(cell, XConstant):
-            return Constant(cell.value)
+        # SpaceOperation, all we have are SomeValues.  But SpaceOperations take
+        # Variables, not SomeValues.  Trouble is, we don't always have a
+        # Variable that just happens to be bound to the given SomeValue.
+        # A typical example would be if the tuple of arguments was created
+        # from another basic block or even another function.  Well I guess
+        # there is no clean solution.
+        vlist = self.heap.queryconstant(cell)
+        if len(vlist) == 1:
+            return Constant(vlist[0])
         else:
+            cell = self.heap.normalized(cell)
             for v in known_variables:
                 if self.bindings[v] == cell:
                     return v
             else:
-                raise CannotSimplify
+                raise IDontKnow, cell
 
     def simplify(self):
         # Generic simpliciations
@@ -161,7 +146,7 @@
     def bindinputargs(self, block, inputcells):
         # Create the initial bindings for the input args of a block.
         for a, cell in zip(block.inputargs, inputcells):
-            self.bindings[a] = cell
+            self.bindings[a] = self.heap.normalized(cell)
         self.annotated[block] = False  # must flowin.
 
     def mergeinputargs(self, block, inputcells):
@@ -173,9 +158,11 @@
             cell1 = self.bindings[a]   # old binding
             oldcells.append(cell1)
             newcells.append(self.heap.merge(cell1, cell2))
+        # if the merged cells changed, we must redo the analysis
+        oldcells = [self.heap.normalized(c) for c in oldcells]
+        newcells = [self.heap.normalized(c) for c in newcells]
         #print '** oldcells = ', oldcells
         #print '** newcells = ', newcells
-        # if the merged cells changed, we must redo the analysis
         if newcells != oldcells:
             self.bindinputargs(block, newcells)
 
@@ -191,71 +178,80 @@
 
     def consider_op(self,op):
         argcells = [self.binding(a) for a in op.args]
-        resultcell = self.bindnew(op.result)
-        consider_meth = getattr(self,'consider_op_'+op.opname,None)
-        if consider_meth is not None:
-            consider_meth(argcells, resultcell, self.transaction())
-
-    def consider_op_add(self, (arg1,arg2), result, t):
-        type1 = t.get_type(arg1)
-        type2 = t.get_type(arg2)
-        if type1 is int and type2 is int:
-            t.set_type(result, int)
-        elif type1 in (int, long) and type2 in (int, long):
-            t.set_type(result, long)
-        if type1 is str and type2 is str:
-            t.set_type(result, str)
-        if type1 is list and type2 is list:
-            t.set_type(result, list)
+        consider_meth = getattr(self,'consider_op_'+op.opname,
+                                self.default_consider_op)
+        try:
+            resultcell = consider_meth(*argcells)
+        except IDontKnow:
+            resultcell = SomeValue()
+        if resultcell is blackholevalue:
+            raise DelayAnnotation  # the operation cannot succeed
+        assert isinstance(resultcell, SomeValue)
+        assert isinstance(op.result, Variable)
+        self.bindings[op.result] = resultcell   # bind resultcell to op.result
+
+    def default_consider_op(self, *args):
+        return SomeValue()
+
+    def consider_op_add(self, arg1, arg2):
+        result = SomeValue()
+        tp = self.heap.checktype
+        if tp(arg1, int) and tp(arg2, int):
+            self.heap.settype(result, int)
+        elif tp(arg1, (int, long)) and tp(arg2, (int, long)):
+            self.heap.settype(result, long)
+        if tp(arg1, str) and tp(arg2, str):
+            self.heap.settype(result, str)
+        if tp(arg1, list) and tp(arg2, list):
+            self.heap.settype(result, list)
             # XXX propagate information about the type of the elements
+        return result
+
+    def consider_op_mul(self, arg1, arg2):
+        result = SomeValue()
+        tp = self.heap.checktype
+        if tp(arg1, int) and tp(arg2, int):
+            self.heap.settype(result, int)
+        elif tp(arg1, (int, long)) and tp(arg2, (int, long)):
+            self.heap.settype(result, long)
+        return result
 
-    def consider_op_mul(self, (arg1,arg2), result, t):
-        type1 = t.get_type(arg1)
-        type2 = t.get_type(arg2)
-        if type1 is int and type2 is int:
-            t.set_type(result, int)
-        elif type1 in (int, long) and type2 in (int, long):
-            t.set_type(result, long)
-
-    def consider_op_inplace_add(self, (arg1,arg2), result, t):
-        type1 = t.get_type(arg1)
-        type2 = t.get_type(arg1)
-        if type1 is list and type2 is list:
+    def consider_op_inplace_add(self, arg1, arg2):
+        tp = self.heap.checktype
+        if tp(arg1, list) and tp(arg2, list):
             # Annotations about the items of arg2 are merged with the ones about
             # the items of arg1.  arg2 is not modified during this operation.
             # result is arg1.
-            result.share(arg1)
-            t.delete('len', [arg1])
-            item1 = t.get('getitem', [arg1, None])
-            if item1 is not None:
-                item2 = t.get('getitem', [arg2, None])
-                if item2 is None:
-                    item2 = XCell()   # anything at all
+            self.heap.delete(ANN.len[arg1, ...])
+            item1 = self.heap.get_del(ANN.getitem[arg1, intvalue, QUERYARG])
+            if item1:
+                item2 = self.heap.get(ANN.getitem[arg2, intvalue, QUERYARG])
+                item2 = item2 or SomeValue()  # defaults to "can be anything"
                 item3 = self.heap.merge(item1, item2)
-                if item3 != item1:
-                    t.delete('getitem', [arg1, None])
-                    t.set('getitem', [arg1, self.any_int], item3)
+                self.heap.set(ANN.getitem[arg1, intvalue, item3])
+            return arg1
         else:
-            self.consider_op_add((arg1,arg2), result, t)
+            return self.consider_op_add(arg1, arg2)
 
-    def consider_op_sub(self, (arg1,arg2), result, t):
-        type1 = t.get_type(arg1)
-        type2 = t.get_type(arg2)
-        if type1 is int and type2 is int:
-            t.set_type(result, int)
-        elif type1 in (int, long) and type2 in (int, long):
-            t.set_type(result, long)
+    def consider_op_sub(self, arg1, arg2):
+        result = SomeValue()
+        tp = self.heap.checktype
+        if tp(arg1, int) and tp(arg2, int):
+            self.heap.settype(result, int)
+        elif tp(arg1, (int, long)) and tp(arg2, (int, long)):
+            self.heap.settype(result, long)
+        return result
 
     consider_op_and_ = consider_op_sub # trailing underline
     consider_op_inplace_lshift = consider_op_sub
 
-    def consider_op_is_true(self, (arg,), result, t):
-        t.set_type(result, bool)
+    def consider_op_is_true(self, arg):
+        return boolvalue
 
     consider_op_not_ = consider_op_is_true
 
-    def consider_op_lt(self, (arg1,arg2), result, t):
-        t.set_type(result, bool)
+    def consider_op_lt(self, arg1, arg2):
+        return boolvalue
 
     consider_op_le = consider_op_lt
     consider_op_eq = consider_op_lt
@@ -263,90 +259,88 @@
     consider_op_gt = consider_op_lt
     consider_op_ge = consider_op_lt
 
-    def consider_op_newtuple(self, args, result, t):
-        t.set_type(result,tuple)
-        t.set("len", [result], self.constant(len(args)))
+    def consider_op_newtuple(self, *args):
+        result = SomeValue()
+        self.heap.settype(result, tuple)
+        self.heap.set(ANN.len[result, self.constant(len(args))])
         for i in range(len(args)):
-            t.set("getitem", [result, self.constant(i)], args[i])
+            self.heap.set(ANN.getitem[result, self.constant(i), args[i]])
+        return result
 
-    def consider_op_newlist(self, args, result, t):
-        t.set_type(result, list)
-        t.set("len", [result], self.constant(len(args)))
-        item_cell = nothingyet
+    def consider_op_newlist(self, *args):
+        result = SomeValue()
+        self.heap.settype(result, list)
+        self.heap.set(ANN.len[result, self.constant(len(args))])
+        item_cell = blackholevalue
         for a in args:
             item_cell = self.heap.merge(item_cell, a)
-        t.set("getitem", [result, self.any_int], item_cell)
+        self.heap.set(ANN.getitem[result, intvalue, item_cell])
+        return result
 
-    def consider_op_newslice(self, args, result, t):
-        t.set_type(result, slice)
+    def consider_op_newslice(self, *args):
+        return slicevalue
 
-    def consider_op_newdict(self, args, result, t):
-        t.set_type(result, dict)
+    def consider_op_newdict(self, *args):
+        result = SomeValue()
+        self.heap.settype(result, dict)
         if not args:
-            t.set("len", [result], self.constant(0))
+            self.heap.set(ANN.len[result, self.constant(0)])
+        return result
+
+    def consider_op_getitem(self, arg1, arg2):
+        tp = self.heap.checktype
+        result = self.heap.get(ANN.getitem[arg1, arg2, QUERYARG])
+        if result:
+            return result
+        if tp(arg2, int):  # not too nice, but needed for lists
+            result = self.heap.get(ANN.getitem[arg1, intvalue, QUERYARG])
+            if result:
+                return result
+        result = SomeValue()
+        if tp(arg2, slice):
+            self.heap.copytype(arg1, result)
+        return result
 
-    def consider_op_getitem(self, (arg1,arg2), result, t):
-        type1 = t.get_type(arg1)
-        type2 = t.get_type(arg2)
-        if type1 in (list, tuple) and type2 is slice:
-            t.set_type(result, type1)
-
-    def decode_simple_call(self, varargs_cell, varkwds_cell, t):
-        len_cell = t.get('len', [varargs_cell])
-        if not isinstance(len_cell, XConstant):
-            return None
-        nbargs = len_cell.value
-        arg_cells = [t.get('getitem', [varargs_cell, self.constant(j)])
+    def decode_simple_call(self, varargs_cell, varkwds_cell):
+        len_cell = self.heap.get(ANN.len[varargs_cell, QUERYARG])
+        nbargs = self.heap.getconstant(len_cell)
+        arg_cells = [self.heap.get(ANN.getitem[varargs_cell,
+                                               self.constant(j), QUERYARG])
                      for j in range(nbargs)]
         if None in arg_cells:
-            return None
-        len_cell = t.get('len', [varkwds_cell])
-        if not isinstance(len_cell, XConstant):
-            return None
-        nbkwds = len_cell.value
+            raise IDontKnow
+        len_cell = self.heap.get(ANN.len[varkwds_cell, QUERYARG])
+        nbkwds = self.heap.getconstant(len_cell)
         if nbkwds != 0:
-            return None
+            raise IDontKnow
         return arg_cells
 
-    def consider_op_call(self, (func,varargs,kwargs), result, t):
-        if not isinstance(func, XConstant):
-            return
-        func = func.value
+    def consider_op_call(self, func, varargs, kwargs):
+        func = self.heap.getconstant(func)
         if isinstance(func, FunctionType) and self.translator:
-            args = self.decode_simple_call(varargs, kwargs, t)
-            if args is not None:
-                result_cell = self.translator.consider_call(self, func, args)
-                if result_cell is nothingyet:
-                    raise DelayAnnotation
-                # 'result' is made shared with 'result_cell'.  This has the
-                # effect that even if result_cell is actually an XConstant,
-                # result stays an XCell, but the annotations about the constant
-                # are also appliable to result.  This is bad because it means
-                # functions returning constants won't propagate the constant
-                # but only e.g. its type.  This is needed at this point because
-                # XConstants are not too well supported in the forward_deps
-                # lists: forward_deps cannot downgrade XConstant to XCell.
-                result.share(result_cell)
+            args = self.decode_simple_call(varargs, kwargs)
+            return self.translator.consider_call(self, func, args)
 
         # XXX: generalize this later
+        tp = self.heap.checktype
+        result = SomeValue()
         if func is range:
-            t.set_type(result, list)
+            self.heap.settype(result, list)
         if func is pow:
-            tp1 = t.get_type(t.get('getitem', [varargs, self.constant(0)]))
-            tp2 = t.get_type(t.get('getitem', [varargs, self.constant(1)]))
-            if tp1 is int and tp2 is int:
-                t.set_type(result, int)
-
-    def consider_const(self,to_var,const):
-        t = self.transaction()
-        t.set('immutable', [], to_var)
-        t.set_type(to_var,type(const.value))
-        if isinstance(const.value, tuple):
-            pass # XXX say something about the elements
+            args = self.decode_simple_call(varargs, kwargs)
+            if len(args) == 2:
+                if tp(args[0], int) and tp(args[1], int):
+                    self.heap.settype(result, int)
+        return result
 
+    def consider_const(self, constvalue):
+        result = self.heap.newconstant(constvalue)
+        self.heap.set(ANN.immutable[result])
+        self.heap.settype(result, type(constvalue))
+        if isinstance(constvalue, tuple):
+            pass # XXX say something about the elements
+        return result
 
-class CannotSimplify(Exception):
-    pass
 
 class DelayAnnotation(Exception):
     pass

Deleted: /pypy/trunk/src/pypy/translator/test/test_annheap.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/test/test_annheap.py	Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,250 +0,0 @@
-
-import autopath
-from pypy.tool import test
-
-from pypy.translator.annotation import XCell, XConstant, nothingyet, Annotation
-from pypy.translator.annheap import AnnotationHeap, Transaction
-
-
-class TestAnnotationHeap(test.IntTestCase):
-
-    def setUp(self):
-        self.c1 = XCell()
-        self.c2 = XCell()
-        self.c3 = XConstant(-2)
-
-    def assertSameSet(self, a, b):
-        a = list(a)
-        b = list(b)
-        # try to reorder a to match b, without failing if the lists
-        # are different -- this will be checked by assertEquals()
-        for i in range(len(b)):
-            try:
-                j = i + a[i:].index(b[i])
-            except ValueError:
-                pass
-            else:
-                a[i], a[j] = a[j], a[i]
-        self.assertEquals(a, b)
-
-    def test_enumerate(self):
-        lst = [Annotation('add', [self.c1, self.c3], self.c2)]
-        a = AnnotationHeap(lst)
-        self.assertSameSet(a.enumerate(), lst)
-
-    def test_simplify(self):
-        lst = [Annotation('add', [self.c1, self.c3], self.c2),
-               Annotation('add', [self.c1, self.c2], self.c2),
-               Annotation('neg', [self.c2], self.c3)]
-        a = AnnotationHeap(lst)
-        a.simplify()
-        self.assertSameSet(a, lst)
-        
-        self.c2.share(self.c3)
-        a.simplify()
-        self.assertSameSet(a, lst[1:])
-
-    def test_simplify_kill(self):
-        ann1 = Annotation('add', [self.c1, self.c3], self.c2)
-        lst = [ann1,
-               Annotation('add', [self.c1, self.c2], self.c2),
-               Annotation('neg', [self.c2], self.c3)]
-        a = AnnotationHeap(lst)
-        a.simplify(kill=[ann1])
-        self.assertSameSet(a, lst[1:])
-
-    def test_simplify_kill_deps(self):
-        ann1 = Annotation('add', [self.c1, self.c3], self.c2)
-        ann2 = Annotation('add', [self.c1, self.c2], self.c2)
-        ann3 = Annotation('add', [self.c1, self.c1], self.c2)
-        ann1.forward_deps.append(ann2)
-        ann2.forward_deps.append(ann3)
-        lst = [ann1, ann2, ann3,
-               Annotation('neg', [self.c2], self.c3)]
-        a = AnnotationHeap(lst)
-        a.simplify(kill=[ann1])
-        self.assertSameSet(a, lst[3:])
-
-    def test_merge_nothingyet(self):
-        lst = [Annotation('add', [self.c1, self.c3], self.c2),
-               Annotation('neg', [self.c2], self.c3)]
-        a = AnnotationHeap(lst)
-        # (c3) inter (all annotations) == (c3)
-        c = a.merge(self.c3, nothingyet)
-        self.assertEquals(c, self.c3)
-        self.failIfEqual(c, nothingyet)
-        self.assertSameSet(a, lst)
-
-    def test_merge_mutable1(self):
-        lst = [Annotation('type', [self.c1], self.c3),
-               Annotation('type', [self.c2], self.c3),
-               Annotation('somethingelse', [self.c2, self.c3], self.c3)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c2) == (c1 shared with c2)
-        c = a.merge(self.c1, self.c2)
-        self.assertEquals(c, self.c1)
-        self.assertEquals(c, self.c2)
-        self.assertEquals(self.c1, self.c2)
-        self.assertSameSet(a, [Annotation('type', [c], self.c3)])
-
-    def test_merge_mutable2(self):
-        lst = [Annotation('type', [self.c1], self.c3),
-               Annotation('type', [self.c2], self.c3),
-               Annotation('somethingelse', [self.c1, self.c3], self.c3)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c2) == (c1 shared with c2)
-        c = a.merge(self.c1, self.c2)
-        self.assertEquals(c, self.c1)
-        self.assertEquals(c, self.c2)
-        self.assertEquals(self.c1, self.c2)
-        self.assertSameSet(a, [Annotation('type', [c], self.c3)])
-
-    def test_merge_immutable(self):
-        lst = [Annotation('type', [self.c1], self.c3),
-               Annotation('type', [self.c2], self.c3),
-               Annotation('immutable', [], self.c1),
-               Annotation('immutable', [], self.c2),
-               Annotation('somethingelse', [self.c2, self.c3], self.c3)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c2) == (some new c4)
-        c = a.merge(self.c1, self.c2)
-        self.failIfEqual(self.c1, self.c2)
-        # c could be equal to c1 here, but we don't require that
-        for op in [Annotation('type', [c], self.c3),
-                   Annotation('immutable', [], c)]:
-            if op not in lst:
-                lst.append(op)
-        self.assertSameSet(a, lst)
-
-    def test_merge_mutable_ex(self):
-        lst = [Annotation('add', [self.c1, self.c2], self.c2),
-               Annotation('neg', [self.c2], self.c1),
-               Annotation('add', [self.c3, self.c2], self.c2),
-               Annotation('immutable', [], self.c2)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c3) == (c1 shared with c3)
-        c = a.merge(self.c1, self.c3)
-        self.assertEquals(c, self.c1)
-        self.assertEquals(c, self.c3)
-        self.assertEquals(self.c1, self.c3)
-        self.assertSameSet(a, [lst[0], lst[3]])
-        self.assertSameSet(a, [lst[2], lst[3]])
-
-    def test_merge_immutable_ex(self):
-        lst = [Annotation('add', [self.c1, self.c2], self.c2),
-               Annotation('neg', [self.c2], self.c1),
-               Annotation('add', [self.c3, self.c2], self.c2),
-               Annotation('immutable', [], self.c1),
-               Annotation('immutable', [], self.c2),
-               Annotation('immutable', [], self.c3)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c3) == (some new c4)
-        c = a.merge(self.c1, self.c3)
-        self.failIfEqual(c, self.c1)
-        self.failIfEqual(c, self.c3)
-        lst += [Annotation('add', [c, self.c2], self.c2),
-                Annotation('immutable', [], c)]
-        self.assertSameSet(a, lst)
-
-    def dont_test_merge_mutable_ex(self):
-        # This test is expected to fail at this point because the algorithms
-        # are not 100% theoretically correct, but probably quite good and
-        # clear enough right now.  In theory in the intersection below
-        # 'add' should be kept.  In practice the extra 'c3' messes things
-        # up.  I can only think about much-more-obscure algos to fix that.
-        lst = [Annotation('add', [self.c1, self.c3], self.c2),
-               Annotation('neg', [self.c2], self.c1),
-               Annotation('add', [self.c3, self.c3], self.c2),
-               Annotation('immutable', [], self.c2)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c3) == (c1 shared with c3)
-        c = a.merge(self.c1, self.c3)
-        self.assertEquals(c, self.c1)
-        self.assertEquals(c, self.c3)
-        self.assertEquals(self.c1, self.c3)
-        self.assertSameSet(a, [lst[0], lst[3]])
-        self.assertSameSet(a, [lst[2], lst[3]])
-
-    def dont_test_merge_immutable_ex(self):
-        # Disabled -- same as above.
-        lst = [Annotation('add', [self.c1, self.c3], self.c2),
-               Annotation('neg', [self.c2], self.c1),
-               Annotation('add', [self.c3, self.c3], self.c2),
-               Annotation('immutable', [], self.c1),
-               Annotation('immutable', [], self.c2),
-               Annotation('immutable', [], self.c3)]
-        a = AnnotationHeap(lst)
-        # (c1) inter (c3) == (some new c4)
-        c = a.merge(self.c1, self.c3)
-        self.failIfEqual(c, self.c1)
-        self.failIfEqual(c, self.c3)
-        lst += [Annotation('add', [c, self.c3], self.c2),
-                Annotation('immutable', [], c)]
-        self.assertSameSet(a, lst)
-
-
-class TestTransaction(test.IntTestCase):
-
-    def setUp(self):
-        self.c1 = XCell()
-        self.c2 = XCell()
-        self.c3 = XConstant(-2)
-        self.lst = [Annotation('add', [self.c1, self.c3], self.c2),
-                    Annotation('neg', [self.c2], self.c1),
-                    Annotation('add', [self.c3, self.c3], self.c2),
-                    Annotation('immutable', [], self.c1),
-                    Annotation('type', [self.c1], self.c3),
-                    Annotation('type', [self.c3], self.c2)]
-        self.a = AnnotationHeap(self.lst)
-
-    def test_get(self):
-        t = Transaction(self.a)
-        self.assertEquals(t.get('add', [self.c1, self.c3]), self.c2)
-        self.assertEquals(t.get('add', [self.c1, self.c2]), None)
-        self.assertEquals(t.get('sub', [self.c1, self.c3]), None)
-
-    def test_get_None(self):
-        t = Transaction(self.a)
-        self.assertEquals(t.get('add', [self.c1, None]), self.c2)
-        self.assertEquals(t.get('add', [None, self.c3]), self.c2)
-        self.assertEquals(t.get('add', [self.c2, None]), None)
-        self.assertEquals(t.get('type', [None]), None)
-
-    def test_get_type(self):
-        t = Transaction(self.a)
-        self.assertEquals(t.get_type(self.c1), -2)
-        self.assertEquals(t.get_type(self.c2), None)
-        self.assertEquals(t.get_type(self.c3), None)
-
-    def test_set(self):
-        t = Transaction(self.a)
-        t.set('dummy', [self.c2], self.c1)
-        self.assertEquals(t.get('dummy', [self.c2]), self.c1)
-
-    def test_set_type(self):
-        t = Transaction(self.a)
-        t.set_type(self.c2, int)
-        self.assertEquals(t.get('type', [self.c2]), XConstant(int))
-
-    def test_dep_set(self):
-        t = Transaction(self.a)
-        t.get('add', [self.c1, self.c3])
-        t.get_type(self.c1)
-        t.set('dummy', [self.c2], self.c1)
-        new_ann = Annotation('dummy', [self.c2], self.c1)
-        self.cases = []
-        for ann in self.a.enumerate():
-            if ann == Annotation('add', [self.c1, self.c3], self.c2):
-                self.cases.append(0)
-                self.assertEquals(ann.forward_deps, [new_ann])
-            elif ann == Annotation('type', [self.c1], self.c3):
-                self.cases.append(1)
-                self.assertEquals(ann.forward_deps, [new_ann])
-            else:
-                self.assertEquals(ann.forward_deps, [])
-        self.cases.sort()
-        self.assertEquals(self.cases, [0, 1])
-
-
-if __name__ == '__main__':
-    test.main()

Deleted: /pypy/trunk/src/pypy/translator/test/test_annotation.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/test/test_annotation.py	Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,46 +0,0 @@
-
-import autopath
-from pypy.tool import test
-
-from pypy.translator.annotation import XCell, XConstant, nothingyet, Annotation
-
-
-class TestAnnotation(test.IntTestCase):
-
-    def test_is_shared(self):
-        c1 = XCell()
-        c2 = XCell()
-        c3 = XCell()
-        c4 = XCell()
-        for a in (c1,c2,c3,c4):
-            for b in (c1,c2,c3,c4):
-                if a is not b:
-                    self.failIfEqual(a, b)
-        c1.share(c2)
-        c4.share(c2)
-        c1.share(c3)
-        for a in (c1,c2,c3,c4):
-            for b in (c1,c2,c3,c4):
-                self.assert_(a.is_shared(b))
-                self.assertEquals(a, b)
-
-    def test_constant(self):
-        self.assertEquals(XConstant(5), XConstant(5))
-        self.failIfEqual(XConstant(5), XConstant(6))
-        self.failIfEqual(XConstant(5), XCell())
-
-    def test_annotation(self):
-        c1 = XCell()
-        c2 = XCell()
-        c3 = XCell()
-        a1 = Annotation('hello', [c1], c2)
-        a2 = Annotation('hello', [c1], c3)
-
-        self.assertEquals(a1, a1)
-        self.failIfEqual (a1, a2)
-        c2.share(c3)
-        self.assertEquals(a1, a2)
-
-
-if __name__ == '__main__':
-    test.main()

Modified: pypy/trunk/src/pypy/translator/translator.py
==============================================================================
--- pypy/trunk/src/pypy/translator/translator.py	(original)
+++ pypy/trunk/src/pypy/translator/translator.py	Thu Dec 18 13:16:53 2003
@@ -31,11 +31,12 @@
 import test.autopath
 
 from pypy.objspace.flow.model import *
-from pypy.translator.annotation import *
+from pypy.annotation.model import *
+from pypy.annotation.annset import *
 from pypy.translator.annrpython import RPythonAnnotator
 from pypy.translator.simplify import simplify_graph
-from pypy.translator.genpyrex import GenPyrex
-from pypy.translator.gencl import GenCL
+#from pypy.translator.genpyrex import GenPyrex
+#from pypy.translator.gencl import GenCL
 from pypy.translator.tool.buildpyxmodule import make_module_from_pyxstring
 from pypy.objspace.flow import FlowObjSpace
 


More information about the Pypy-commit mailing list