[pypy-svn] r4209 - in pypy/branch/typeinference/pypy: annotation annotation/test translator

arigo at codespeak.net arigo at codespeak.net
Fri Apr 30 21:03:20 CEST 2004


Author: arigo
Date: Fri Apr 30 21:03:14 2004
New Revision: 4209

Added:
   pypy/branch/typeinference/pypy/annotation/binaryop.py   (contents, props changed)
   pypy/branch/typeinference/pypy/annotation/factory.py   (contents, props changed)
   pypy/branch/typeinference/pypy/annotation/pairtype.py   (contents, props changed)
   pypy/branch/typeinference/pypy/annotation/test/test_model.py   (contents, props changed)
Removed:
   pypy/branch/typeinference/pypy/annotation/annset.py
   pypy/branch/typeinference/pypy/annotation/test/test_annset.py
Modified:
   pypy/branch/typeinference/pypy/annotation/model.py
   pypy/branch/typeinference/pypy/translator/annrpython.py
   pypy/branch/typeinference/pypy/translator/genpyrex.py
   pypy/branch/typeinference/pypy/translator/transform.py
   pypy/branch/typeinference/pypy/translator/translator.py
Log:
First try.

   annotation.model     contains the basic Some* classes
   annotation.binaryop  has the logic for the union, plus other binary ops
   annotation.test.test_model

Together they replace the horribly obscure annotation.annset and its merge 
nightmare, which is gone together with its test suite.

   annotation.factory   factories remember how to create mutable objects

The rest (in pypy/translator) is in a no-test-passing state, but very simple 
functions like simple_func (i -> i+1) can already be successfully analysed and 
Pyrexed with translator/translator.py.


Deleted: /pypy/branch/typeinference/pypy/annotation/annset.py
==============================================================================
--- /pypy/branch/typeinference/pypy/annotation/annset.py	Fri Apr 30 21:03:14 2004
+++ (empty file)
@@ -1,209 +0,0 @@
-from __future__ import generators
-import types
-from model import SomeValue, ANN, immutable_types
-
-
-class MostGeneralValue:
-    def __nonzero__(self):
-        return False
-mostgeneralvalue = MostGeneralValue()
-
-class ImpossibleValue(Exception):
-    pass
-impossiblevalue = ImpossibleValue()
-
-
-class About:
-    def __init__(self):
-        # 'annotations' maps Predicates to tuples
-        #   (SomeValue, {set-of-blocks-depending-on-this-annotation})
-        self.annotations = {}
-        self.subjects = {}  # set of SomeValues we are about
-    def __repr__(self):    # debugging
-        subjs = [repr(c) for c in self.subjects]
-        subjs.sort()
-        lines = ['About %s:' % ' and '.join(subjs)]
-        annotations = [(str(pred), value)
-                       for pred, (value, deps) in self.annotations.items()]
-        annotations.sort()
-        for name, somevalue in annotations:
-            lines.append('%15s --> %r' % (name, somevalue))
-        return '\n'.join(lines)
-
-
-class AnnotationSet:
-    """An annotation set is a (large) family of annotations."""
-
-    # This is basically a mapping {SomeValue(): About()}
-    # with convenient methods.
-
-    def __init__(self):
-        self.about = {}
-        self.inblock = None
-
-    def enter(self, block, callback):
-        self.inblock = block
-        self.callback = callback
-
-    def leave(self):
-        self.inblock = None
-
-    def isshared(self, val1, val2):
-        return self.about.get(val1, val1) == self.about.get(val2, val2)
-
-    def __repr__(self):     # debugging
-        lines = ['=====  AnnotationSet  =====']
-        abouts = [(repr(somevalue), about)
-                  for somevalue, about in self.about.items()]
-        abouts.sort()
-        alreadyseen = {}
-        for name, about in abouts:
-            if about not in alreadyseen:
-                if about.annotations:  # ignore empty Abouts
-                    lines.append(repr(about))
-                alreadyseen[about] = True
-        return '\n'.join(lines)
-
-    def get(self, predicate, subject):
-        if subject is not mostgeneralvalue:
-            about = self._about(subject)
-            result = about.annotations.get(predicate)
-            if result:
-                answer, dependencies = result
-                if self.inblock:
-                    dependencies[self.inblock] = True
-                return answer
-        return mostgeneralvalue
-
-    def _about(self, somevalue):
-        try:
-            return self.about[somevalue]
-        except KeyError:
-            if somevalue is mostgeneralvalue:
-                raise ValueError, "Unexpected mostgeneralvalue"
-            if isinstance(somevalue, ImpossibleValue):
-                raise somevalue
-            about = self.about[somevalue] = About()
-            about.subjects[somevalue] = True
-            return about
-
-    def set(self, predicate, subject, answer):
-        about = self._about(subject)
-        if predicate in about.annotations:
-            raise ValueError, "There is already an annotation for %r" % subject
-        if answer is not mostgeneralvalue:
-            about.annotations[predicate] = answer, {}
-
-    def kill(self, predicate, subject):
-        about = self._about(subject)
-        if predicate in about.annotations:
-            someval, deps = about.annotations[predicate]
-            del about.annotations[predicate]
-            # perform invalidations
-            for block in deps:
-                self.callback(block)
-
-    def generalize(self, predicate, subject, otherpossibleanswer):
-        """Generalize the given annotation to also account for the given
-        answer."""
-        # We shouldn't record a dependency so
-        # we can't just do 'oldanswer = self.get(predicate, subject)'
-        oldanswer = mostgeneralvalue
-        if subject is not mostgeneralvalue:
-            about = self._about(subject)
-            old = about.annotations.get(predicate)
-            if old:
-                oldanswer, dependencies = old
-        newanswer = self.merge(oldanswer, otherpossibleanswer)
-        if not self.isshared(oldanswer, newanswer):
-            self.kill(predicate, subject)
-            self.set(predicate, subject, newanswer)
-
-    def set_or_generalize(self, predicate, subject, otherpossibleanswer):
-        """This is a hack.  Do not use for SomeValues that could be merged."""
-        about = self._about(subject)
-        if predicate in about.annotations:
-            self.generalize(predicate, subject, otherpossibleanswer)
-        else:
-            self.set(predicate, subject, otherpossibleanswer)
-
-    def merge(self, oldvalue, newvalue):
-        """Update the heap to account for the merging of oldvalue and newvalue.
-        Return the merged somevalue."""
-        if isinstance(newvalue, ImpossibleValue):
-            return oldvalue
-        if isinstance(oldvalue, ImpossibleValue):
-            return newvalue
-        if newvalue is mostgeneralvalue or oldvalue is mostgeneralvalue:
-            return mostgeneralvalue
-        if self.isshared(oldvalue, newvalue):
-            return oldvalue
-
-        if not (isinstance(oldvalue, SomeValue) and
-                isinstance(newvalue, SomeValue)):
-            return mostgeneralvalue
-        
-        # build an About set that is the intersection of the two incoming ones
-        about1 = self._about(oldvalue)
-        about2 = self._about(newvalue)
-        about3 = About()
-        for pred in about1.annotations:
-            if pred in about2.annotations:
-                someval1, dep1 = about1.annotations[pred]
-                someval2, dep2 = about2.annotations[pred]
-                if someval1 == someval2:
-                    someval3 = someval1
-                else:
-                    someval3 = self.merge(someval1, someval2)
-                    if someval3 is mostgeneralvalue:
-                        continue # annotation not in common
-                dep3 = dep1.copy()
-                dep3.update(dep2)
-                about3.annotations[pred] = someval3, dep3
-
-        # if 'oldvalue' or 'newvalue' is immutable, we should not
-        # modify the annotations about it.  If one of them is mutable,
-        # then we must replace its About set with 'about3'.
-        invalidatedblocks = {}
-        for about in [about1, about2]:
-            # find all annotations that are removed or generalized
-            removedannotations = []
-            for pred, (someval, deps) in about.annotations.items():
-                if (pred in about3.annotations and
-                    self.isshared(about3.annotations[pred][0], someval)):
-                    continue   # unmodified annotation
-                removedannotations.append(deps)
-            # if the existing 'value' is mutable, or if nothing has been
-            # removed, then we identify (by sharing) the 'value' and the
-            # new 'about3'.
-            if not removedannotations or ANN.immutable not in about.annotations:
-                # patch 'value' to use the new 'about3'.
-                for sharedvalue in about.subjects:   # this includes 'value'
-                    self.about[sharedvalue] = about3
-                    about3.subjects[sharedvalue] = True
-                for deps in removedannotations:
-                    invalidatedblocks.update(deps)
-
-        if not about3.subjects:
-            value3 = SomeValue()
-            self.about[value3] = about3
-            about3.subjects[value3] = True
-
-        # perform invalidations
-        for block in invalidatedblocks:
-            self.callback(block)
-        
-        return about3.subjects.iterkeys().next()
-
-    def checktype(self, someval, checktype):
-        knowntype = self.get(ANN.type, someval)
-        return knowntype and issubclass(knowntype, checktype)
-
-    def settype(self, someval, knowntype):
-        self.set(ANN.type, someval, knowntype)
-        if knowntype in immutable_types:
-            self.set(ANN.immutable, someval, True)
-
-    def copytype(self, oldcell, newcell):
-        self.set(ANN.type, newcell, self.get(ANN.type, oldcell))
-        self.set(ANN.immutable, newcell, self.get(ANN.immutable, oldcell))

Added: pypy/branch/typeinference/pypy/annotation/binaryop.py
==============================================================================
--- (empty file)
+++ pypy/branch/typeinference/pypy/annotation/binaryop.py	Fri Apr 30 21:03:14 2004
@@ -0,0 +1,98 @@
+"""
+Binary operations between SomeValues.
+"""
+
+from pypy.annotation.pairtype import pair, pairtype
+from pypy.annotation.model import SomeObject, SomeInteger, SomeString, SomeList
+from pypy.annotation.model import SomeTuple, SomeImpossibleValue
+
+
+def setunion(d1, d2):
+    "Union of two sets represented as dictionaries."
+    d = d1.copy()
+    d.update(d2)
+    return d
+
+
+BINARY_OPERATIONS = {'add': True,
+                     'sub': True,
+                     'union': True,
+                     }
+
+class __extend__(pairtype(SomeObject, SomeObject)):
+    # default case
+
+    for name in BINARY_OPERATIONS:
+        locals()[name] = lambda *dummy: SomeObject()
+    del name
+
+
+class __extend__(pairtype(SomeInteger, SomeInteger)):
+
+    def union((int1, int2)):
+        return SomeInteger(nonneg = int1.nonneg and int2.nonneg)
+
+    def add((int1, int2)):
+        return SomeInteger(nonneg = int1.nonneg and int2.nonneg)
+
+    def sub((int1, int2)):
+        return SomeInteger()
+
+
+class __extend__(pairtype(SomeString, SomeString)):
+
+    def union((str1, str2)):
+        return SomeString()
+
+    def add((str1, str2)):
+        return SomeString()
+
+
+class __extend__(pairtype(SomeList, SomeList)):
+
+    def union((lst1, lst2)):
+        return SomeList(setunion(lst1.factories, lst2.factories),
+                        s_item = pair(lst1.s_item, lst2.s_item).union())
+
+    add = union
+
+
+class __extend__(pairtype(SomeTuple, SomeTuple)):
+
+    def union((tup1, tup2)):
+        if len(tup1.items) != len(tup2.items):
+            return SomeObject()
+        else:
+            unions = [pair(x,y).union() for x,y in zip(tup1.items, tup2.items)]
+            return SomeTuple(items = unions)
+
+    def add((tup1, tup2)):
+        return SomeTuple(items = tup1.items + tup2.items)
+
+
+class __extend__(pairtype(SomeList, SomeInteger)):
+    
+    def mul((lst1, int2)):
+        return lst1
+
+    def getitem((lst1, int2)):
+        return lst1.s_item
+
+    def setitem((lst1, int2), value):
+        if not lst1.s_item.contains(value):
+            raise NeedGeneralization(lst1, value)
+
+
+class __extend__(pairtype(SomeInteger, SomeList)):
+    
+    def mul((int1, lst2)):
+        return lst2
+
+
+class __extend__(pairtype(SomeImpossibleValue, SomeObject)):
+    def union((imp1, obj2)):
+        return obj2
+
+class __extend__(pairtype(SomeObject, SomeImpossibleValue)):
+    def union((obj1, imp2)):
+        return obj1

Added: pypy/branch/typeinference/pypy/annotation/factory.py
==============================================================================
--- (empty file)
+++ pypy/branch/typeinference/pypy/annotation/factory.py	Fri Apr 30 21:03:14 2004
@@ -0,0 +1,42 @@
+"""
+Mutable Objects Factories.
+
+A factory is associated to each point in the source that creates a mutable
+object.  The factory remembers how general an object it has to create here.
+
+"""
+
+from pypy.annotation.pairtype import pair
+from pypy.annotation.model import SomeImpossibleValue
+
+
+class BlockedInference(Exception):
+    """This exception signals the type inference engine that the situation
+    is currently blocked, and that it should try to progress elsewhere."""
+
+class NeedGeneralization(BlockedInference):
+    """The mutable object s_mutable requires generalization.
+    The *args are passed to the generalize() method of the factory."""
+
+    def __init__(self, s_mutable, *args):
+        BlockedInference.__init__(self, s_mutable, *args)
+        for factory in s_mutable.factories:
+            factory.generalize(*args)
+
+
+#
+#  Factories
+#
+
+class ListFactory:
+
+    def __init__(self, block):
+        self.block = block     # block containing the list creation op
+        self.s_item = SomeImpossibleValue()
+
+    def create(self):
+        return SomeList(factories = {self: True}, s_item = self.s_item)
+
+    def generalize(self, s_new_item):
+        self.s_item = pair(self.s_item, s_new_item).union()
+        self.block.invalidate()

Modified: pypy/branch/typeinference/pypy/annotation/model.py
==============================================================================
--- pypy/branch/typeinference/pypy/annotation/model.py	(original)
+++ pypy/branch/typeinference/pypy/annotation/model.py	Fri Apr 30 21:03:14 2004
@@ -1,52 +1,105 @@
-import types
+"""
+This file defines the 'subset' SomeValue classes.
 
-class SomeValue:
-    def __repr__(self):
-        return debugname(self, 'SV')
-
-class Predicate:
-    def __init__(self, debugname):
-        self.debugname = debugname
-    def __str__(self):
-        return self.debugname
-
-class PredicateFamily:
-    def __init__(self, familyname):
-        self.familyname = familyname
-        self.instances = {}
-    def __getitem__(self, index):
-        try:
-            return self.instances[index]
-        except KeyError:
-            name = '%s[%r]' % (self.familyname, index)
-            pred = self.instances[index] = Predicate(name)
-            return pred
-
-class ANN:
-    len       = Predicate('len')
-    listitems = Predicate('listitems')
-    tupleitem = PredicateFamily('tupleitem')
-    const     = Predicate('const')
-    type      = Predicate('type')
-    immutable = Predicate('immutable')
-    instanceattr = PredicateFamily('instanceattr')
-
-
-def debugname(someval, prefix, _seen = {}):
-    """ return a simple name for a SomeValue. """
-    try:
-        return _seen[id(someval)]
-    except KeyError:
-        name = "%s%d" % (prefix, len(_seen))
-        _seen[id(someval)] = name
-        return name
-
-immutable_types = {
-    int: 'int',
-    long: 'long',
-    tuple: 'tuple',
-    str: 'str',
-    bool: 'bool',
-    slice: 'slice',
-    types.FunctionType: 'function',
-    }
+An instance of a SomeValue class stands for a Python object that has some
+known properties, for example that is known to be a list of non-negative
+integers.  Each instance can be considered as an object that is only
+'partially defined'.  Another point of view is that each instance is a
+generic element in some specific subset of the set of all objects.
+
+"""
+
+# Old terminology still in use here and there:
+#    SomeValue means one of the SomeXxx classes in this file.
+#    Cell is an instance of one of these classes.
+#
+# Think about cells as potato-shaped circles in a diagram:
+#    ______________________________________________________
+#   / SomeObject()                                         \
+#  /   ___________________________          ______________  \
+#  |  / SomeInteger(nonneg=False) \____    / SomeString() \  \
+#  | /     __________________________  \   |              |  |
+#  | |    / SomeInteger(nonneg=True) \ |   |      "hello" |  |
+#  | |    |   0    42       _________/ |   \______________/  |
+#  | \ -3 \________________/           /                     |
+#  \  \                     -5   _____/                      /
+#   \  \________________________/              3.1416       /
+#    \_____________________________________________________/
+#
+
+
+from pypy.annotation.pairtype import pair
+
+
+class SomeObject:
+    """The set of all objects.  Each instance stands
+    for an arbitrary object about which nothing is known."""
+    knowntype = None
+    def __eq__(self, other):
+        return (self.__class__, self.__dict__) == (other.__class__, other.__dict__)
+    def __ne__(self, other):
+        return not (self == other)
+    def contains(self, other):
+        return pair(self, other).union() == self
+
+class SomeInteger(SomeObject):
+    "Stands for an object which is known to be an integer."
+    knowntype = int
+    def __init__(self, nonneg=False):
+        self.nonneg = nonneg
+
+class SomeBool(SomeInteger):
+    "Stands for true or false."
+    knowntype = bool
+    def __init__(self):
+        SomeInteger.__init__(nonneg=True)
+
+class SomeString(SomeObject):
+    "Stands for an object which is known to be a string."
+    knowntype = str
+
+class SomeList(SomeObject):
+    "Stands for a homogenous list of any length."
+    knowntype = list
+    def __init__(self, factories, s_item=SomeObject()):
+        self.factories = factories
+        self.s_item = s_item     # general enough for any element
+
+class SomeTuple(SomeObject):
+    "Stands for a tuple of known length."
+    knowntype = tuple
+    def __init__(self, items):
+        self.items = tuple(items)   # tuple of s_xxx elements
+
+class SomeImpossibleValue(SomeObject):
+    """The empty set.  Instances are placeholders for objects that
+    will never show up at run-time, e.g. elements of an empty list."""
+
+
+def immutablevalue(x):
+    "The most precise SomeValue instance that contains the immutable value x."
+    if isinstance(bool, type) and isinstance(x, bool):
+        return SomeBool()
+    elif isinstance(x, int):
+        return SomeInteger(nonneg = x>=0)
+    elif isinstance(x, str):
+        return SomeString()
+    elif isinstance(x, tuple):
+        return SomeTuple(items = [immutablevalue(e) for e in x])
+    else:
+        return SomeObject()
+
+def valueoftype(t):
+    "The most precise SomeValue instance that contains all objects of type t."
+    if isinstance(bool, type) and issubclass(t, bool):
+        return SomeBool()
+    elif issubclass(t, int):
+        return SomeInteger()
+    elif issubclass(t, str):
+        return SomeString()
+    elif issubclass(t, list):
+        return SomeList(factories={})
+
+
+# this has the side-effect of registering the binary operations
+from pypy.annotation.binaryop import BINARY_OPERATIONS

Added: pypy/branch/typeinference/pypy/annotation/pairtype.py
==============================================================================
--- (empty file)
+++ pypy/branch/typeinference/pypy/annotation/pairtype.py	Fri Apr 30 21:03:14 2004
@@ -0,0 +1,130 @@
+"""
+XXX A docstring should go here.
+"""
+
+class extendabletype(type):
+    """A type with a syntax trick: 'class __extend__(t)' actually extends
+    the definition of 't' instead of creating a new subclass."""
+    def __new__(cls, name, bases, dict):
+        if name == '__extend__':
+            cls = bases[0]   # override data into the existing base
+            for key, value in dict.items():
+                setattr(cls, key, value)
+            return None
+        else:
+            return super(extendabletype, cls).__new__(cls, name, bases, dict)
+
+
+def pair(a, b):
+    """Return a pair object."""
+    tp = pairtype(a.__class__, b.__class__)
+    return tp((a, b))   # tp is a subclass of tuple
+
+pairtypecache = {}
+
+def pairtype(cls1, cls2):
+    """type(pair(a,b)) is pairtype(a.__class__, b.__class__)."""
+    try:
+        pair = pairtypecache[cls1, cls2]
+    except KeyError:
+        name = 'pairtype(%s, %s)' % (cls1.__name__, cls2.__name__)
+        bases1 = [pairtype(base1, cls2) for base1 in cls1.__bases__]
+        bases2 = [pairtype(cls1, base2) for base2 in cls2.__bases__]
+        bases = tuple(bases1 + bases2) or (tuple,)  # 'tuple': ultimate base
+        pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {})
+    return pair
+
+
+# ____________________________________________________________
+
+if __name__ == '__main__':
+    from unittest2 import check
+    
+    ### Binary operation example
+    class __extend__(pairtype(int, int)):
+        def add((x, y)):
+            return 'integer: %s+%s' % (x, y)
+        def sub((x, y)):
+            return 'integer: %s-%s' % (x, y)
+
+    class __extend__(pairtype(bool, bool)):
+        def add((x, y)):
+            return 'bool: %s+%s' % (x, y)
+
+    check.equal(pair(3,4).add(), 'integer: 3+4')
+    check.equal(pair(3,4).sub(), 'integer: 3-4')
+    check.equal(pair(3,True).add(), 'integer: 3+True')
+    check.equal(pair(3,True).sub(), 'integer: 3-True')
+    check.equal(pair(False,4).add(), 'integer: False+4')
+    check.equal(pair(False,4).sub(), 'integer: False-4')
+    check.equal(pair(False,True).add(), 'bool: False+True')
+    check.equal(pair(False,True).sub(), 'integer: False-True')
+
+    ### Operation on built-in types
+    class MiniPickler:
+        def __init__(self):
+            self.data = []
+        def emit(self, datum):
+            self.data.append(datum)
+
+    class __extend__(pairtype(MiniPickler, int)):
+        def write((pickler, x)):
+            pickler.emit('I%d' % x)
+
+    class __extend__(pairtype(MiniPickler, str)):
+        def write((pickler, x)):
+            pickler.emit('S%s' % x)
+
+    class __extend__(pairtype(MiniPickler, list)):
+        def write((pickler, x)):
+            for item in x:
+                pair(pickler, item).write()
+            pickler.emit('L%d' % len(x))
+
+    p = MiniPickler()
+    pair(p, [1, 2, ['hello', 3]]).write()
+    check.equal(p.data, ['I1', 'I2', 'Shello', 'I3', 'L2', 'L3'])
+
+    ### Another multimethod example
+    class Block:
+        def __init__(self, exit):
+            self.exit = exit
+    class Jump:
+        pass
+    class Switch:
+        pass
+    
+    class C_Generator:
+        def __init__(self):
+            self.lines = []
+
+    class __extend__(pairtype(C_Generator, Block)):
+        def emit((gen, block), inputvars):
+            gen.lines.append("C code for block")
+            outputvars = inputvars + ['v4', 'v5']
+            pair(gen, block.exit).emit(outputvars)
+
+    class __extend__(pairtype(C_Generator, Jump)):
+        def emit((gen, jump), inputvars):
+            gen.lines.append("goto xyz")
+
+    class __extend__(pairtype(C_Generator, Switch)):
+        def emit((gen, jump), inputvars):
+            gen.lines.append("switch (%s) { ... }" % inputvars[-1])
+
+    g = C_Generator()
+    pair(g, Block(Switch())).emit(['v1', 'v2'])
+    check.equal(g.lines, ["C code for block",
+                          "switch (v5) { ... }"])
+
+    class Lisp_Generator:
+        def __init__(self):
+            self.progn = []
+
+    class __extend__(pairtype(Lisp_Generator, Block)):
+        def emit((gen, block), inputvars):
+            gen.progn.append("(do 'something)")
+
+    g = Lisp_Generator()
+    pair(g, Block(Switch())).emit(['v1', 'v2'])
+    check.equal(g.progn, ["(do 'something)"])

Deleted: /pypy/branch/typeinference/pypy/annotation/test/test_annset.py
==============================================================================
--- /pypy/branch/typeinference/pypy/annotation/test/test_annset.py	Fri Apr 30 21:03:14 2004
+++ (empty file)
@@ -1,229 +0,0 @@
-
-import autopath
-from pypy.tool import testit
-
-from pypy.annotation.model import SomeValue, ANN, Predicate
-from pypy.annotation.annset import AnnotationSet, mostgeneralvalue,impossiblevalue
-
-
-c1,c2,c3,c4 = SomeValue(), SomeValue(), SomeValue(), SomeValue()
-c5,c6,c7,c8 = SomeValue(), SomeValue(), SomeValue(), SomeValue()
-
-def annset(*args, **kwds):
-    "This constructor is just a convenient hack for the tests."
-    annset = AnnotationSet()
-    groups = []
-    for a in args:
-        if isinstance(a, Predicate):
-            groups.append([a])
-        else:
-            groups[-1].append(a)    # hack hack hack
-    for args in groups:
-        if len(args) == 2:
-            args = args + [True]    #   "   "    "
-        annset.set(*args)
-    if 'links' in kwds:
-        links = kwds['links']
-        for i in range(0, len(links), 2):
-            if annset.about.get(links[i]) != annset.about.get(links[i+1]):
-                assert links[i] not in annset.about
-                about = annset.about[links[i]] = annset.about[links[i+1]]
-                about.subjects[links[i]] = True
-    return annset
-
-
-class TestAnnotationSet(testit.IntTestCase):
-
-    def assertSameSet(self, annset1, annset2):
-        self.assertEquals(repr(annset1), repr(annset2))
-    
-    def assertSameCells(self, annset, firstcell, *cells):
-        for cell in cells:
-            self.assert_(annset.isshared(firstcell, cell))
-
-    def test_trivial(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        a2 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        self.assertSameSet(a1, a2)
-
-    def test_get(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        self.assertEquals(a1.get(ANN.len, c1), c2)
-        self.assertEquals(a1.get(ANN.len, c2), mostgeneralvalue)
-
-    def test_set(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        a1.set(ANN.len, c2, c3)
-        self.assertSameSet(a1,
-             annset(ANN.len, c1, c2,
-                    ANN.type, c2, int,
-                    ANN.len, c2, c3))
-
-    def test_kill(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        for i in range(2):
-            a1.kill(ANN.len, c1)
-            self.assertSameSet(a1,
-                 annset(ANN.type, c2, int))
-
-    def test_merge_mostgeneralvalue(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        a2 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, int)
-        # (c3) inter (mostgeneralvalue) == (mostgeneralvalue)
-        c = a1.merge(c3, mostgeneralvalue)
-        self.assertEquals(c, mostgeneralvalue)
-        self.assertSameSet(a1, a2)
-
-    def test_merge_mutable1(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.len, c3, c2)
-        a2 = annset(ANN.len, c1, c2, links=[c3,c1])
-        # (c1) inter (c3) == (c1 shared with c3)
-        c = a1.merge(c1, c3)
-        self.assertSameCells(a1, c, c1, c3)
-        self.assertSameSet(a1, a2)
-
-    def test_merge_mutable2(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.len, c3, c2,
-                    ANN.type, c1, list,
-                    ANN.type, c2, str)
-        a2 = annset(ANN.len, c1, c2,
-                    ANN.type, c2, str,
-                    links=[c3,c1])
-        # (c1) inter (c3) == (c1 shared with c3)
-        c = a1.merge(c1, c3)
-        self.assertSameCells(a1, c, c1, c3)
-        self.assertSameSet(a1, a2)
-
-    def test_merge_same_immutables(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.immutable, c1,
-                    ANN.len, c3, c2,
-                    ANN.immutable, c3)
-        # (c1) inter (c3) == (c1 and c3)
-        c = a1.merge(c1, c3)
-        self.assertSameCells(a1, c, c1, c3)
-        a2 = annset(ANN.len, c, c2,
-                    ANN.immutable, c,
-                    links=[c1,c,c3,c])
-        self.assertSameSet(a1, a2)
-
-    def test_merge_generalize_one_immutable(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.immutable, c1,
-                    ANN.type, c1, list,
-                    ANN.len, c3, c2,
-                    ANN.immutable, c3,
-                    ANN.type, c2, str)
-        # (c1) inter (c3) == (c3)
-        c = a1.merge(c1, c3)
-        self.assertSameCells(a1, c, c3)
-        a2 = annset(ANN.len, c1, c2,
-                    ANN.immutable, c1,
-                    ANN.type, c1, list,
-                    ANN.len, c, c2,
-                    ANN.immutable, c,
-                    ANN.type, c2, str,
-                    links=[c3,c])
-        self.assertSameSet(a1, a2)
-
-    def test_level2_merge_w_impossible(self):
-        a1 = annset(ANN.type, c1, list,
-                    ANN.listitems, c1, impossiblevalue,
-                    ANN.type, c2, list,
-                    ANN.listitems, c2, c3,
-                    ANN.type, c3, int)
-        c = a1.merge(c1,c2)
-        a2 = annset(ANN.type, c , list,
-                    ANN.listitems, c, c3,
-                    ANN.type, c3, int,
-                    links=[c1,c])
-        self.assertSameSet(a1,a2)
-                    
-    def test_merge_generalize_both_immutables(self):
-        a1 = annset(ANN.len, c1, c2,
-                    ANN.immutable, c1,
-                    ANN.type, c1, list,
-                    ANN.len, c3, c2,
-                    ANN.immutable, c3,
-                    ANN.type, c3, tuple,
-                    ANN.type, c2, str)
-        # (c1) inter (c3) == (a more general c)
-        c = a1.merge(c1, c3)
-        a2 = annset(ANN.len, c1, c2,
-                    ANN.immutable, c1,
-                    ANN.type, c1, list,
-                    ANN.len, c3, c2,
-                    ANN.immutable, c3,
-                    ANN.type, c3, tuple,
-                    ANN.len, c, c2,
-                    ANN.immutable, c,
-                    ANN.type, c2, str)
-        self.assertSameSet(a1, a2)
-
-    def test_recursive_merge(self):
-        a1 = annset(ANN.tupleitem[2], c1, c2,
-                    ANN.immutable, c1,
-                    ANN.type, c2, list,
-                    ANN.listitems, c2, c3,
-                    ANN.type, c3, int,
-                    ANN.immutable, c3,
-                    ANN.tupleitem[2], c5, c6,
-                    ANN.immutable, c5,
-                    ANN.type, c6, list,
-                    ANN.listitems, c6, c7,
-                    ANN.type, c7, float,
-                    ANN.immutable, c7)
-        c9  = a1.merge(c1, c5)
-        c10 = a1.get(ANN.tupleitem[2], c9)
-        c11 = a1.get(ANN.listitems, c10)
-        self.assertSameCells(a1, c1, c5, c9)
-        self.assertSameCells(a1, c2, c6, c10)
-        
-        a2 = annset(ANN.tupleitem[2], c9, c10,
-                    ANN.immutable, c9,
-                    ANN.type, c10, list,
-                    ANN.listitems, c10, c11,
-                    ANN.immutable, c11,
-                    # old remaining stuff
-                    ANN.type, c3, int,
-                    ANN.immutable, c3,
-                    ANN.type, c7, float,
-                    ANN.immutable, c7,
-                    links=[c1,c9, c5,c9, c2,c10, c6,c10])
-        self.assertSameSet(a1, a2)
-
-    def test_settype(self):
-        a = annset()
-        a.settype(c1, int)
-        a.settype(c2, list)
-        self.assertSameSet(a,
-            annset(ANN.type, c1, int,
-                   ANN.immutable, c1,
-                   ANN.type, c2, list))
-
-    def test_copytype(self):
-        a = annset(ANN.type, c1, int,
-                   ANN.immutable, c1,
-                   ANN.type, c2, list)
-        a.copytype(c1, c3)
-        a.copytype(c2, c4)
-        self.assertSameSet(a,
-            annset(ANN.type, c1, int,
-                   ANN.immutable, c1,
-                   ANN.type, c2, list,
-                   ANN.type, c3, int,
-                   ANN.immutable, c3,
-                   ANN.type, c4, list))
-
-
-if __name__ == '__main__':
-    testit.main()

Added: pypy/branch/typeinference/pypy/annotation/test/test_model.py
==============================================================================
--- (empty file)
+++ pypy/branch/typeinference/pypy/annotation/test/test_model.py	Fri Apr 30 21:03:14 2004
@@ -0,0 +1,45 @@
+
+import autopath
+from pypy.annotation.model import *
+
+
+s1 = SomeObject()
+s2 = SomeInteger(nonneg=True)
+s3 = SomeInteger(nonneg=False)
+s4 = SomeList({}, SomeTuple([SomeInteger(nonneg=True), SomeString()]))
+s5 = SomeList({}, SomeTuple([SomeInteger(nonneg=False), SomeString()]))
+s6 = SomeImpossibleValue()
+slist = [s1,s2,s3,s4,s5,s6]
+
+def test_equality():
+    assert s1 != s2 != s3 != s4 != s5 != s6
+    assert s1 == SomeObject()
+    assert s2 == SomeInteger(nonneg=True)
+    assert s3 == SomeInteger(nonneg=False)
+    assert s4 == SomeList({}, SomeTuple([SomeInteger(nonneg=True), SomeString()]))
+    assert s5 == SomeList({}, SomeTuple([SomeInteger(nonneg=False), SomeString()]))
+    assert s6 == SomeImpossibleValue()
+
+def test_contains():
+    assert ([(s,t) for s in slist for t in slist if s.contains(t)] ==
+            [(s1,s1), (s1,s2), (s1,s3), (s1,s4), (s1,s5), (s1,s6),
+                      (s2,s2),                            (s2,s6),
+                      (s3,s2), (s3,s3),                   (s3,s6),
+                                        (s4,s4),          (s4,s6),
+                                        (s5,s4), (s5,s5), (s5,s6),
+                                                          (s6,s6)])
+
+def test_union():
+    assert ([pair(s,t).union() for s in slist for t in slist] ==
+            [s1, s1, s1, s1, s1, s1,
+             s1, s2, s3, s1, s1, s2,
+             s1, s3, s3, s1, s1, s3,
+             s1, s1, s1, s4, s5, s4,
+             s1, s1, s1, s5, s5, s5,
+             s1, s2, s3, s4, s5, s6])
+
+
+if __name__ == '__main__':
+    for name, value in globals().items():
+        if name.startswith('test_'):
+            value()

Modified: pypy/branch/typeinference/pypy/translator/annrpython.py
==============================================================================
--- pypy/branch/typeinference/pypy/translator/annrpython.py	(original)
+++ pypy/branch/typeinference/pypy/translator/annrpython.py	Fri Apr 30 21:03:14 2004
@@ -1,9 +1,9 @@
 from __future__ import generators
 
 from types import FunctionType
-from pypy.annotation.model import SomeValue, ANN
-from pypy.annotation.annset import AnnotationSet
-from pypy.annotation.annset import impossiblevalue, mostgeneralvalue
+from pypy.annotation import model as annmodel
+from pypy.annotation.model import pair
+from pypy.annotation.factory import ListFactory, BlockedInference
 from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant
 from pypy.objspace.flow.model import SpaceOperation
 
@@ -11,34 +11,29 @@
 class AnnotatorError(Exception):
     pass
 
-intvalue = SomeValue()
-boolvalue = SomeValue()
-
 
 class RPythonAnnotator:
     """Block annotator for RPython.
     See description in doc/transation/annotation.txt."""
 
     def __init__(self, translator=None):
-        self.heap = AnnotationSet()
-        self.heap.settype(intvalue,  int)
-        self.heap.settype(boolvalue, bool)
         self.pendingblocks = []  # list of (block, list-of-SomeValues-args)
         self.delayedblocks = []  # list of blocked blocks
-        self.bindings = {}       # map Variables/Constants to SomeValues
+        self.bindings = {}       # map Variables to SomeValues
         self.annotated = {}      # set of blocks already seen
+        self.creationpoints = {} # map SpaceOperations to Factories
         self.translator = translator
-        self.userclasses = {}    # set of user classes discovered,
-                                 # mapped to sets of instance attributes
 
     #___ convenience high-level interface __________________
 
     def build_types(self, flowgraph, input_arg_types):
         """Recursively build annotations about the specific entry point."""
         # make input arguments and set their type
-        inputcells = [SomeValue() for arg in flowgraph.getargs()]
-        for cell, arg_type in zip(inputcells, input_arg_types):
-            self.heap.settype(cell, arg_type)
+        input_arg_types = list(input_arg_types)
+        nbarg = len(flowgraph.getargs())
+        while input_arg_types < nbarg:
+            input_arg_types.append(object)
+        inputcells = [annmodel.valueoftype(t) for t in input_arg_types]
         
         # register the entry point
         self.addpendingblock(flowgraph.startblock, inputcells)
@@ -52,27 +47,13 @@
         elif isinstance(variable, Variable):
             cell = self.bindings.get(variable)
             if cell:
-                cell = self.heap.get(ANN.type, cell)
-                if cell:
-                    return cell
-            return None
+                return cell.knowntype
+            else:
+                return None
         else:
             raise TypeError, ("Variable or Constant instance expected, "
                               "got %r" % (variable,))
 
-    def getuserclasses(self):
-        """Return a set of known user classes."""
-        return self.userclasses
-
-    def getuserattributes(self, cls):
-        """Enumerate the attributes of the given user class, as Variable()s."""
-        for attr in self.userclasses[cls]:
-            clscell = self.constant(cls)
-            attrcell = self.heap.get(ANN.instanceattr[attr], clscell)
-            v = Variable(name=attr)
-            self.bindings[v] = attrcell
-            yield v
-
 
     #___ medium-level interface ____________________________
 
@@ -84,9 +65,8 @@
         """Process pending blocks until none is left."""
         while self.pendingblocks:
             # XXX don't know if it is better to pop from the head or the tail.
-            # let's do it breadth-first and pop from the head (oldest first).
-            # that's more stacklessy.
-            block, cells = self.pendingblocks.pop(0)
+            # but suspect from the tail is better in the new Factory model.
+            block, cells = self.pendingblocks.pop()
             self.processblock(block, cells)
         if self.delayedblocks:
             raise AnnotatorError('%d block(s) are still blocked' %
@@ -94,21 +74,18 @@
 
     def binding(self, arg):
         "Gives the SomeValue corresponding to the given Variable or Constant."
-        try:
+        if isinstance(arg, Variable):
             return self.bindings[arg]
-        except KeyError:
-            if not isinstance(arg, Constant):
-                raise   # propagate missing bindings for Variables
-            if isinstance(arg, UndefinedConstant):
-                result = impossiblevalue  # undefined local variables
-            else:
-                result = self.consider_const(arg.value)
-            self.bindings[arg] = result
-            return result
+        elif isinstance(arg, UndefinedConstant):  # undefined local variables
+            return annmodel.SomeImpossibleValue()
+        elif isinstance(arg, Constant):
+            return annmodel.immutablevalue(arg.value)
+        else:
+            raise TypeError, 'Variable or Constant expected, got %r' % (arg,)
 
     def constant(self, value):
         "Turn a value into a SomeValue with the proper annotations."
-        return self.binding(Constant(value))
+        return annmodel.immutablevalue(arg.value)
 
 
     #___ simplification (should be moved elsewhere?) _______
@@ -166,7 +143,7 @@
             self.annotated[block] = True
             try:
                 self.flowin(block)
-            except DelayAnnotation:
+            except BlockedInference:
                 self.annotated[block] = False   # failed, hopefully temporarily
                 self.delayedblocks.append(block)
             else:
@@ -190,25 +167,15 @@
     def mergeinputargs(self, block, inputcells):
         # Merge the new 'cells' with each of the block's existing input
         # variables.
-        oldcells = []
-        newcells = []
-        for a, cell2 in zip(block.inputargs, inputcells):
-            cell1 = self.bindings[a]   # old binding
-            oldcells.append(cell1)
-            newcells.append(self.heap.merge(cell1, cell2))
+        oldcells = [self.binding(a) for a in block.inputargs]
+        unions = [pair(c1,c2).union() for c1, c2 in zip(oldcells, inputcells)]
         # if the merged cells changed, we must redo the analysis
-        #print '** oldcells = ', oldcells
-        #print '** newcells = ', newcells
-        for cell1, cell2 in zip(oldcells, newcells):
-            if not self.heap.isshared(cell1, cell2):
-                self.bindinputargs(block, newcells)
-                return
+        if unions != oldcells:
+            self.bindinputargs(block, newcells)
 
     def flowin(self, block):
-        self.heap.enter(block, self.reflowpendingblock)
         for op in block.operations:
             self.consider_op(op)
-        self.heap.leave()
         for link in block.exits:
             cells = [self.binding(a) for a in link.args]
             self.addpendingblock(link.target, cells)
@@ -218,202 +185,204 @@
 
     def consider_op(self,op):
         argcells = [self.binding(a) for a in op.args]
-        consider_meth = getattr(self,'consider_op_'+op.opname,
-                                self.default_consider_op)
-        resultcell = consider_meth(*argcells)
-        if resultcell is impossiblevalue:
-            raise DelayAnnotation  # the operation cannot succeed
-        assert isinstance(resultcell, (SomeValue, type(mostgeneralvalue)))
+
+        if op.opname in annmodel.BINARY_OPERATIONS:
+            resultcell = getattr(pair(*argcells), op.opname)()
+        else:
+            consider_meth = getattr(self,'consider_op_'+op.opname,
+                                    self.default_consider_op)
+            resultcell = consider_meth(*argcells)
+        if resultcell == annmodel.SomeImpossibleValue():
+            raise BlockedInference  # the operation cannot succeed
+        assert isinstance(resultcell, annmodel.SomeObject)
         assert isinstance(op.result, Variable)
         self.bindings[op.result] = resultcell   # bind resultcell to op.result
 
-    def consider_op_setattr(self,obj,attr,newval):
-        objtype = self.heap.get(ANN.type,obj)
-        if objtype in self.userclasses:
-            attr = self.heap.get(ANN.const,attr)
-            if isinstance(attr, str):
-                # do we already know about this attribute?
-                attrdict = self.userclasses[objtype]
-                clscell = self.constant(objtype)
-                if attr not in attrdict:
-                    # no -> create it
-                    attrdict[attr] = True
-                    self.heap.set(ANN.instanceattr[attr], clscell, newval)
-                else:
-                    # yes -> update it
-                    self.heap.generalize(ANN.instanceattr[attr], clscell, newval)
-        return SomeValue()
-
-    def consider_op_getattr(self,obj,attr):
-        result = SomeValue()
-        objtype = self.heap.get(ANN.type,obj)
-        if objtype in self.userclasses:
-            attr = self.heap.get(ANN.const,attr)
-            if isinstance(attr, str):
-                # do we know something about this attribute?
-                attrdict = self.userclasses[objtype]
-                if attr in attrdict:
-                    # yes -> return the current annotation
-                    clscell = self.constant(objtype)
-                    return self.heap.get(ANN.instanceattr[attr], clscell)
-        return result
-        
-
     def default_consider_op(self, *args):
-        return mostgeneralvalue
+        return annmodel.SomeObject()
 
-    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_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.
-            self.heap.kill(ANN.len, arg1)
-            item2 = self.heap.get(ANN.listitems, arg2)
-            self.heap.generalize(ANN.listitems, arg1, item2)
-            return arg1
-        else:
-            return self.consider_op_add(arg1, arg2)
 
-    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_mod  = consider_op_sub
-    consider_op_inplace_lshift = consider_op_sub
-
-    def consider_op_is_true(self, arg):
-        return boolvalue
-
-    consider_op_not_ = consider_op_is_true
-
-    def consider_op_lt(self, arg1, arg2):
-        return boolvalue
-
-    consider_op_le = consider_op_lt
-    consider_op_eq = consider_op_lt
-    consider_op_ne = consider_op_lt
-    consider_op_gt = consider_op_lt
-    consider_op_ge = consider_op_lt
-
-    def consider_op_newtuple(self, *args):
-        result = SomeValue()
-        self.heap.settype(result, tuple)
-        self.heap.set(ANN.len, result, len(args))
-        for i in range(len(args)):
-            self.heap.set(ANN.tupleitem[i], result, args[i])
-        return result
-
-    def consider_op_newlist(self, *args):
-        result = SomeValue()
-        self.heap.settype(result, list)
-        self.heap.set(ANN.len, result, len(args))
-        item_cell = impossiblevalue
-        for a in args:
-            item_cell = self.heap.merge(item_cell, a)
-        self.heap.set(ANN.listitems, result, item_cell)
-        return result
-
-    def consider_op_newslice(self, *args):
-        result = SomeValue()
-        self.heap.settype(result, slice)
-        return result
-
-    def consider_op_newdict(self, *args):
-        result = SomeValue()
-        self.heap.settype(result, dict)
-        if not args:
-            self.heap.set(ANN.len, result, 0)
-        return result
-
-    def consider_op_getitem(self, arg1, arg2):
-        tp = self.heap.checktype
-        if tp(arg2, int):
-            if tp(arg1, tuple):
-                index = self.heap.get(ANN.const, arg2)
-                if index is not mostgeneralvalue:
-                    return self.heap.get(ANN.tupleitem[index], arg1)
-            if tp(arg1, list):
-                return self.heap.get(ANN.listitems, arg1)
-        result = SomeValue()
-        if tp(arg2, slice):
-            self.heap.copytype(arg1, result)
-            # XXX copy some information about the items
-        return result
-
-    def decode_simple_call(self, varargs_cell, varkwds_cell):
-        nbargs = self.heap.get(ANN.len, varargs_cell)
-        if nbargs is mostgeneralvalue:
-            return None
-        arg_cells = [self.heap.get(ANN.tupleitem[j], varargs_cell)
-                     for j in range(nbargs)]
-        nbkwds = self.heap.get(ANN.len, varkwds_cell)
-        if nbkwds != 0:
-            return None  # XXX deal with dictionaries with constant keys
-        return arg_cells
-
-    def consider_op_call(self, func, varargs, kwargs):
-        result = SomeValue()
-        tp = self.heap.checktype
-        func = self.heap.get(ANN.const, func)
-        # XXX: generalize this later
-        if func is range:
-            self.heap.settype(result, list)
-        elif func is pow:
-            args = self.decode_simple_call(varargs, kwargs)
-            if args is not None and len(args) == 2:
-                if tp(args[0], int) and tp(args[1], int):
-                    self.heap.settype(result, int)
-        elif isinstance(func, FunctionType) and self.translator:
-            args = self.decode_simple_call(varargs, kwargs)
-            return self.translator.consider_call(self, func, args)
-        elif isinstance(func,type):
-            # XXX flow into __init__/__new__
-            self.heap.settype(result,func)
-            if func.__module__ != '__builtin__':
-                self.userclasses.setdefault(func, {})
-        return result
-
-    def consider_const(self, constvalue):
-        result = SomeValue()
-        self.heap.set(ANN.const, result, constvalue)
-        self.heap.settype(result, type(constvalue))
-        if isinstance(constvalue, tuple):
-            pass # XXX say something about the elements
-        return result
+##    def consider_op_setattr(self,obj,attr,newval):
+##        objtype = self.heap.get(ANN.type,obj)
+##        if objtype in self.userclasses:
+##            attr = self.heap.get(ANN.const,attr)
+##            if isinstance(attr, str):
+##                # do we already know about this attribute?
+##                attrdict = self.userclasses[objtype]
+##                clscell = self.constant(objtype)
+##                if attr not in attrdict:
+##                    # no -> create it
+##                    attrdict[attr] = True
+##                    self.heap.set(ANN.instanceattr[attr], clscell, newval)
+##                else:
+##                    # yes -> update it
+##                    self.heap.generalize(ANN.instanceattr[attr], clscell, newval)
+##        return SomeValue()
+
+##    def consider_op_getattr(self,obj,attr):
+##        result = SomeValue()
+##        objtype = self.heap.get(ANN.type,obj)
+##        if objtype in self.userclasses:
+##            attr = self.heap.get(ANN.const,attr)
+##            if isinstance(attr, str):
+##                # do we know something about this attribute?
+##                attrdict = self.userclasses[objtype]
+##                if attr in attrdict:
+##                    # yes -> return the current annotation
+##                    clscell = self.constant(objtype)
+##                    return self.heap.get(ANN.instanceattr[attr], clscell)
+##        return result
+        
 
+##    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_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.
+##            self.heap.kill(ANN.len, arg1)
+##            item2 = self.heap.get(ANN.listitems, arg2)
+##            self.heap.generalize(ANN.listitems, arg1, item2)
+##            return arg1
+##        else:
+##            return self.consider_op_add(arg1, arg2)
+
+##    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_mod  = consider_op_sub
+##    consider_op_inplace_lshift = consider_op_sub
+
+##    def consider_op_is_true(self, arg):
+##        return boolvalue
+
+##    consider_op_not_ = consider_op_is_true
+
+##    def consider_op_lt(self, arg1, arg2):
+##        return boolvalue
+
+##    consider_op_le = consider_op_lt
+##    consider_op_eq = consider_op_lt
+##    consider_op_ne = consider_op_lt
+##    consider_op_gt = consider_op_lt
+##    consider_op_ge = consider_op_lt
+
+##    def consider_op_newtuple(self, *args):
+##        result = SomeValue()
+##        self.heap.settype(result, tuple)
+##        self.heap.set(ANN.len, result, len(args))
+##        for i in range(len(args)):
+##            self.heap.set(ANN.tupleitem[i], result, args[i])
+##        return result
+
+##    def consider_op_newlist(self, *args):
+##        result = SomeValue()
+##        self.heap.settype(result, list)
+##        self.heap.set(ANN.len, result, len(args))
+##        item_cell = impossiblevalue
+##        for a in args:
+##            item_cell = self.heap.merge(item_cell, a)
+##        self.heap.set(ANN.listitems, result, item_cell)
+##        return result
+
+##    def consider_op_newslice(self, *args):
+##        result = SomeValue()
+##        self.heap.settype(result, slice)
+##        return result
+
+##    def consider_op_newdict(self, *args):
+##        result = SomeValue()
+##        self.heap.settype(result, dict)
+##        if not args:
+##            self.heap.set(ANN.len, result, 0)
+##        return result
+
+##    def consider_op_getitem(self, arg1, arg2):
+##        tp = self.heap.checktype
+##        if tp(arg2, int):
+##            if tp(arg1, tuple):
+##                index = self.heap.get(ANN.const, arg2)
+##                if index is not mostgeneralvalue:
+##                    return self.heap.get(ANN.tupleitem[index], arg1)
+##            if tp(arg1, list):
+##                return self.heap.get(ANN.listitems, arg1)
+##        result = SomeValue()
+##        if tp(arg2, slice):
+##            self.heap.copytype(arg1, result)
+##            # XXX copy some information about the items
+##        return result
+
+##    def decode_simple_call(self, varargs_cell, varkwds_cell):
+##        nbargs = self.heap.get(ANN.len, varargs_cell)
+##        if nbargs is mostgeneralvalue:
+##            return None
+##        arg_cells = [self.heap.get(ANN.tupleitem[j], varargs_cell)
+##                     for j in range(nbargs)]
+##        nbkwds = self.heap.get(ANN.len, varkwds_cell)
+##        if nbkwds != 0:
+##            return None  # XXX deal with dictionaries with constant keys
+##        return arg_cells
+
+##    def consider_op_call(self, func, varargs, kwargs):
+##        result = SomeValue()
+##        tp = self.heap.checktype
+##        func = self.heap.get(ANN.const, func)
+##        # XXX: generalize this later
+##        if func is range:
+##            self.heap.settype(result, list)
+##        elif func is pow:
+##            args = self.decode_simple_call(varargs, kwargs)
+##            if args is not None and len(args) == 2:
+##                if tp(args[0], int) and tp(args[1], int):
+##                    self.heap.settype(result, int)
+##        elif isinstance(func, FunctionType) and self.translator:
+##            args = self.decode_simple_call(varargs, kwargs)
+##            return self.translator.consider_call(self, func, args)
+##        elif isinstance(func,type):
+##            # XXX flow into __init__/__new__
+##            self.heap.settype(result,func)
+##            if func.__module__ != '__builtin__':
+##                self.userclasses.setdefault(func, {})
+##        return result
+
+##    def consider_const(self, constvalue):
+##        result = SomeValue()
+##        self.heap.set(ANN.const, result, constvalue)
+##        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):
+class CannotSimplify(Exception):
     pass

Modified: pypy/branch/typeinference/pypy/translator/genpyrex.py
==============================================================================
--- pypy/branch/typeinference/pypy/translator/genpyrex.py	(original)
+++ pypy/branch/typeinference/pypy/translator/genpyrex.py	Fri Apr 30 21:03:14 2004
@@ -225,8 +225,8 @@
         vartype = self.get_type(var)
         if vartype in (int, bool):
             prefix = "i_"
-        elif self.annotator and vartype in self.annotator.getuserclasses():
-            prefix = "p_"
+        #elif self.annotator and vartype in self.annotator.getuserclasses():
+        #    prefix = "p_"
         else:
             prefix = ""
         return prefix + var.name
@@ -235,8 +235,8 @@
         vartype = self.get_type(var)
         if vartype in (int, bool):
             ctype = "int"
-        elif self.annotator and vartype in self.annotator.getuserclasses():
-            ctype = self.get_classname(vartype)
+        #elif self.annotator and vartype in self.annotator.getuserclasses():
+        #    ctype = self.get_classname(vartype)
         else:
             ctype = "object"
 
@@ -328,25 +328,24 @@
         self.gen_block(block)
 
     def globaldeclarations(self):
-        """Static method to generate the global class declaration for a
-        group of functions."""
+        """Generate the global class declaration for a group of functions."""
         if self.annotator:
             self.lines = []
             self.indent = 0
-            for cls in self.annotator.getuserclasses():
-                self.putline("cdef class %s:" % self.get_classname(cls))
-                self.indent += 1
-                empty = True
-                for var in self.annotator.getuserattributes(cls):
-                    vartype, varname = self._paramvardecl(var)
-                    varname = var.name   # no 'i_' prefix
-                    self.putline("cdef %s %s" % (vartype, varname))
-                    empty = False
-                else:
-                    if empty:
-                        self.putline("pass")
-                self.indent -= 1
-                self.putline("")
+##            for cls in self.annotator.getuserclasses():
+##                self.putline("cdef class %s:" % self.get_classname(cls))
+##                self.indent += 1
+##                empty = True
+##                for var in self.annotator.getuserattributes(cls):
+##                    vartype, varname = self._paramvardecl(var)
+##                    varname = var.name   # no 'i_' prefix
+##                    self.putline("cdef %s %s" % (vartype, varname))
+##                    empty = False
+##                else:
+##                    if empty:
+##                        self.putline("pass")
+##                self.indent -= 1
+##                self.putline("")
             return '\n'.join(self.lines)
         else:
             return ''

Modified: pypy/branch/typeinference/pypy/translator/transform.py
==============================================================================
--- pypy/branch/typeinference/pypy/translator/transform.py	(original)
+++ pypy/branch/typeinference/pypy/translator/transform.py	Fri Apr 30 21:03:14 2004
@@ -6,8 +6,8 @@
 
 import types
 from pypy.objspace.flow.model import SpaceOperation
-from pypy.annotation.model import SomeValue
-from pypy.translator.annrpython import CannotSimplify
+#from pypy.annotation.model import SomeValue
+#from pypy.translator.annrpython import CannotSimplify
 
 # XXX: Lots of duplicated codes. Fix this!
 

Modified: pypy/branch/typeinference/pypy/translator/translator.py
==============================================================================
--- pypy/branch/typeinference/pypy/translator/translator.py	(original)
+++ pypy/branch/typeinference/pypy/translator/translator.py	Fri Apr 30 21:03:14 2004
@@ -32,7 +32,6 @@
 
 from pypy.objspace.flow.model 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


More information about the Pypy-commit mailing list