[pypy-svn] r4297 - in pypy/trunk/src/pypy: annotation annotation/test translator translator/test translator/tool

arigo at codespeak.net arigo at codespeak.net
Fri May 7 00:24:00 CEST 2004


Author: arigo
Date: Fri May  7 00:24:00 2004
New Revision: 4297

Added:
   pypy/trunk/src/pypy/annotation/binaryop.py   (props changed)
      - copied unchanged from r4295, pypy/branch/typeinference/pypy/annotation/binaryop.py
   pypy/trunk/src/pypy/annotation/factory.py   (props changed)
      - copied unchanged from r4295, pypy/branch/typeinference/pypy/annotation/factory.py
   pypy/trunk/src/pypy/annotation/pairtype.py   (props changed)
      - copied unchanged from r4295, pypy/branch/typeinference/pypy/annotation/pairtype.py
   pypy/trunk/src/pypy/annotation/test/test_model.py   (props changed)
      - copied unchanged from r4295, pypy/branch/typeinference/pypy/annotation/test/test_model.py
   pypy/trunk/src/pypy/annotation/unaryop.py   (props changed)
      - copied unchanged from r4295, pypy/branch/typeinference/pypy/annotation/unaryop.py
Removed:
   pypy/trunk/src/pypy/annotation/annset.py
   pypy/trunk/src/pypy/annotation/test/test_annset.py
Modified:
   pypy/trunk/src/pypy/annotation/model.py
   pypy/trunk/src/pypy/translator/annrpython.py
   pypy/trunk/src/pypy/translator/genpyrex.py
   pypy/trunk/src/pypy/translator/test/snippet.py
   pypy/trunk/src/pypy/translator/test/test_annrpython.py
   pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py
   pypy/trunk/src/pypy/translator/transform.py
   pypy/trunk/src/pypy/translator/translator.py
Log:
Merged typeinference branch back to the trunk.
-r 4208:4294


Deleted: /pypy/trunk/src/pypy/annotation/annset.py
==============================================================================
--- /pypy/trunk/src/pypy/annotation/annset.py	Fri May  7 00:24:00 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))

Modified: pypy/trunk/src/pypy/annotation/model.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/model.py	(original)
+++ pypy/trunk/src/pypy/annotation/model.py	Fri May  7 00:24:00 2004
@@ -1,52 +1,150 @@
-import types
+"""
+This file defines the 'subset' SomeValue classes.
 
-class SomeValue:
+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, extendabletype
+
+
+class SomeObject:
+    """The set of all objects.  Each instance stands
+    for an arbitrary object about which nothing is known."""
+    __metaclass__ = extendabletype
+    knowntype = object
+    def __eq__(self, other):
+        return (self.__class__ is other.__class__ and
+                self.__dict__  == other.__dict__)
+    def __ne__(self, other):
+        return not (self == other)
     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',
-    }
+        kwds = ', '.join(['%s=%r' % item for item in self.__dict__.items()])
+        return '%s(%s)' % (self.__class__.__name__, kwds)
+    def contains(self, other):
+        return self == other or pair(self, other).union() == self
+    def is_constant(self):
+        return hasattr(self, 'const')
+
+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
+    nonneg = True
+    def __init__(self):
+        pass
+
+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
+    def len(self):
+        return immutablevalue(len(self.items))
+
+class SomeInstance(SomeObject):
+    "Stands for an instance of a (user-defined) class."
+    def __init__(self, classdef):
+        self.classdef = classdef
+        self.knowntype = classdef.cls
+        self.revision = classdef.revision
+
+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):
+        result = SomeBool()
+    elif isinstance(x, int):
+        result = SomeInteger(nonneg = x>=0)
+    elif isinstance(x, str):
+        result = SomeString()
+    elif isinstance(x, tuple):
+        result = SomeTuple(items = [immutablevalue(e) for e in x])
+    else:
+        result = SomeObject()
+    result.const = x
+    return result
+
+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={})
+    else:
+        return SomeObject()
+
+
+# ____________________________________________________________
+# internal
+
+def setunion(d1, d2):
+    "Union of two sets represented as dictionaries."
+    d = d1.copy()
+    d.update(d2)
+    return d
+
+def set(it):
+    "Turn an iterable into a set."
+    d = {}
+    for x in it:
+        d[x] = True
+    return d
+
+def missing_operation(cls, name):
+    def default_op(*args):
+        print '* warning, no type available for %s(%s)' % (
+            name, ', '.join([repr(a) for a in args]))
+        return SomeObject()
+    setattr(cls, name, default_op)
+
+# this has the side-effect of registering the unary and binary operations
+from pypy.annotation.unaryop import UNARY_OPERATIONS
+from pypy.annotation.binaryop import BINARY_OPERATIONS

Deleted: /pypy/trunk/src/pypy/annotation/test/test_annset.py
==============================================================================
--- /pypy/trunk/src/pypy/annotation/test/test_annset.py	Fri May  7 00:24:00 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()

Modified: pypy/trunk/src/pypy/translator/annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/annrpython.py	(original)
+++ pypy/trunk/src/pypy/translator/annrpython.py	Fri May  7 00:24:00 2004
@@ -1,9 +1,10 @@
 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 types import FunctionType, ClassType
+from pypy.annotation import model as annmodel
+from pypy.annotation.model import pair
+from pypy.annotation.factory import ListFactory, InstanceFactory
+from pypy.annotation.factory import BlockedInference
 from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant
 from pypy.objspace.flow.model import SpaceOperation
 
@@ -11,34 +12,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 positions-in-blocks to Factories
         self.translator = translator
-        self.userclasses = {}    # set of user classes discovered,
-                                 # mapped to sets of instance attributes
+        self.userclasses = {}    # set of user classes
 
     #___ 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 len(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)
@@ -46,16 +42,16 @@
         self.complete()
 
     def gettype(self, variable):
-        """Return the known type of a control flow graph variable, or None."""
+        """Return the known type of a control flow graph variable,
+        defaulting to 'object'."""
         if isinstance(variable, Constant):
             return type(variable.value)
         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 object
         else:
             raise TypeError, ("Variable or Constant instance expected, "
                               "got %r" % (variable,))
@@ -66,11 +62,10 @@
 
     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)
+        clsdef = self.userclasses[cls]
+        for attr, s_value in clsdef.attrs.items():
             v = Variable(name=attr)
-            self.bindings[v] = attrcell
+            self.bindings[v] = s_value
             yield v
 
 
@@ -78,37 +73,31 @@
 
     def addpendingblock(self, block, cells):
         """Register an entry point into block with the given input cells."""
+        for a in cells:
+            assert isinstance(a, annmodel.SomeObject)
         self.pendingblocks.append((block, cells))
 
     def complete(self):
         """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' %
-                                 len(delayedblocks))
+        if False in self.annotated.values():
+            raise AnnotatorError('%d blocks are still blocked' %
+                                 self.annotated.values().count(False))
 
     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
-
-    def constant(self, value):
-        "Turn a value into a SomeValue with the proper annotations."
-        return self.binding(Constant(value))
+        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,)
 
 
     #___ simplification (should be moved elsewhere?) _______
@@ -125,13 +114,15 @@
         # 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.
-        constvalue = self.heap.get(ANN.const, cell)
-        if constvalue is not mostgeneralvalue:
-            return Constant(constvalue)
+        # there is no clean solution, short of making the transformations
+        # more syntactic (e.g. replacing a specific sequence of SpaceOperations
+        # with another one).  This is a real hack because we have to use
+        # the identity of 'cell'.
+        if cell.is_constant():
+            return Constant(cell.const)
         else:
             for v in known_variables:
-                if self.heap.isshared(self.bindings[v], cell):
+                if self.bindings[v] is cell:
                     return v
             else:
                 raise CannotSimplify
@@ -166,15 +157,14 @@
             self.annotated[block] = True
             try:
                 self.flowin(block)
-            except DelayAnnotation:
+            except BlockedInference, e:
+                #print '_'*60
+                #print 'Blocked at %r:' % (self.curblockpos,)
+                #import traceback, sys
+                #traceback.print_tb(sys.exc_info()[2])
                 self.annotated[block] = False   # failed, hopefully temporarily
-                self.delayedblocks.append(block)
-            else:
-                # When flowin succeeds, i.e. when the analysis progress,
-                # we can tentatively re-schedlue the delayed blocks.
-                for block in self.delayedblocks:
-                    self.addpendingblock(block, None)
-                del self.delayedblocks[:]
+                for factory in e.invalidatefactories:
+                    self.reflowpendingblock(factory.block)
 
     def reflowpendingblock(self, block):
         self.pendingblocks.append((block, None))
@@ -190,29 +180,36 @@
     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, unions)
 
     def flowin(self, block):
-        self.heap.enter(block, self.reflowpendingblock)
-        for op in block.operations:
-            self.consider_op(op)
-        self.heap.leave()
+        #print 'Flowing', block, [self.binding(a) for a in block.inputargs]
+        for i in range(len(block.operations)):
+            self.curblockpos = block, i
+            self.consider_op(block.operations[i])
         for link in block.exits:
             cells = [self.binding(a) for a in link.args]
             self.addpendingblock(link.target, cells)
 
+    def getfactory(self, factorycls, *factoryargs):
+        try:
+            factory = self.creationpoints[self.curblockpos]
+        except KeyError:
+            block = self.curblockpos[0]
+            factory = factorycls(*factoryargs)
+            factory.block = block
+            self.creationpoints[self.curblockpos] = factory
+        # self.curblockpos is an arbitrary key that identifies a specific
+        # position, so that asking twice for a factory from the same position
+        # returns the same factory object.  Because we can ask for several
+        # factories in the same operation, we change self.curblockpos here
+        self.curblockpos = self.curblockpos, 'bis'
+        return factory
+
 
     #___ creating the annotations based on operations ______
 
@@ -221,199 +218,247 @@
         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 resultcell is None:
+            resultcell = annmodel.SomeImpossibleValue()  # no return value
+        elif 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 _registeroperations(loc):
+        # All unary operations
+        for opname in annmodel.UNARY_OPERATIONS:
+            exec """
+def consider_op_%s(self, arg, *args):
+    return arg.%s(*args)
+""" % (opname, opname) in globals(), loc
+        # All binary operations
+        for opname in annmodel.BINARY_OPERATIONS:
+            exec """
+def consider_op_%s(self, arg1, arg2, *args):
+    return pair(arg1,arg2).%s(*args)
+""" % (opname, opname) in globals(), loc
 
-    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
+    _registeroperations(locals())
+    del _registeroperations
 
     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
+        return annmodel.SomeTuple(items = args)
 
     def consider_op_newlist(self, *args):
-        result = SomeValue()
-        self.heap.settype(result, list)
-        self.heap.set(ANN.len, result, len(args))
-        item_cell = impossiblevalue
+        factory = self.getfactory(ListFactory)
         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:
+            factory.generalize(a)
+        return factory.create()
+
+    def decode_simple_call(self, s_varargs, s_varkwds):
+        s_nbargs = s_varargs.len()
+        if not s_nbargs.is_constant():
             return None
-        arg_cells = [self.heap.get(ANN.tupleitem[j], varargs_cell)
+        nbargs = s_nbargs.const
+        arg_cells = [pair(s_varargs, annmodel.immutablevalue(j)).getitem()
                      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
+##        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)
+    def consider_op_call(self, s_func, s_varargs, s_kwargs):
+        if not s_func.is_constant():
+            return annmodel.SomeObject()
+        func = s_func.const
+        
         # XXX: generalize this later
         if func is range:
-            self.heap.settype(result, list)
+            factory = self.getfactory(ListFactory)
+            factory.generalize(annmodel.SomeInteger())  # XXX nonneg=...
+            return factory.create()
         elif func is pow:
-            args = self.decode_simple_call(varargs, kwargs)
+            args = self.decode_simple_call(s_varargs, s_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)
+                if (issubclass(args[0].knowntype, int) and
+                    issubclass(args[1].knowntype, int)):
+                    return annmodel.SomeInteger()
         elif isinstance(func, FunctionType) and self.translator:
-            args = self.decode_simple_call(varargs, kwargs)
+            args = self.decode_simple_call(s_varargs, s_kwargs)
             return self.translator.consider_call(self, func, args)
-        elif isinstance(func,type):
+        elif (isinstance(func, (type, ClassType)) and
+              func.__module__ != '__builtin__'):
             # 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
+            factory = self.getfactory(InstanceFactory, func, self.userclasses)
+            return factory.create()
+        elif isinstance(func,type):
+            return annmodel.valueoftype(func)
+        return annmodel.SomeObject()
 
 
-class CannotSimplify(Exception):
-    pass
+##    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
+        
 
-class DelayAnnotation(Exception):
+##    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_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

Modified: pypy/trunk/src/pypy/translator/genpyrex.py
==============================================================================
--- pypy/trunk/src/pypy/translator/genpyrex.py	(original)
+++ pypy/trunk/src/pypy/translator/genpyrex.py	Fri May  7 00:24:00 2004
@@ -328,8 +328,7 @@
         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

Modified: pypy/trunk/src/pypy/translator/test/snippet.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/snippet.py	(original)
+++ pypy/trunk/src/pypy/translator/test/snippet.py	Fri May  7 00:24:00 2004
@@ -287,3 +287,22 @@
     c.a = 1
     c.a = 2
     return c.a
+
+class D(C): pass
+class E(C): pass
+
+def inheritance1():
+    d = D()
+    d.stuff = ()
+    e = E()
+    e.stuff = -12
+    e.stuff = 3
+    lst = [d, e]
+    return d.stuff, e.stuff
+
+def inheritance2():
+    d = D()
+    d.stuff = (-12, -12)
+    e = E()
+    e.stuff = (3, "world")
+    return C().stuff

Modified: pypy/trunk/src/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/trunk/src/pypy/translator/test/test_annrpython.py	Fri May  7 00:24:00 2004
@@ -3,7 +3,7 @@
 from pypy.tool import testit
 from pypy.tool.udir import udir
 
-from pypy.translator.annrpython import RPythonAnnotator, ANN
+from pypy.translator.annrpython import RPythonAnnotator, annmodel
 from pypy.translator.translator import Translator
 from pypy.objspace.flow.model import *
 
@@ -124,9 +124,7 @@
         # result should be a list of integers
         self.assertEquals(a.gettype(fun.getreturnvar()), list)
         end_cell = a.binding(fun.getreturnvar())
-        item_cell = a.heap.get(ANN.listitems, end_cell)
-        self.assert_(item_cell)
-        self.assertEquals(a.heap.get(ANN.type, item_cell), int)
+        self.assertEquals(end_cell.s_item.knowntype, int)
 
     def test_factorial(self):
         translator = Translator(snippet.factorial)
@@ -152,6 +150,29 @@
         # result should be an integer
         self.assertEquals(a.gettype(graph.getreturnvar()), int)
 
+    def test_inheritance1(self):
+        translator = Translator(snippet.inheritance1)
+        graph = translator.getflowgraph()
+        a = RPythonAnnotator(translator)
+        a.build_types(graph, [])
+        # result should be exactly:
+        self.assertEquals(a.binding(graph.getreturnvar()),
+                          annmodel.SomeTuple([
+                              annmodel.SomeTuple([]),
+                              annmodel.SomeInteger()
+                              ]))
+
+    def test_inheritance2(self):
+        translator = Translator(snippet.inheritance2)
+        graph = translator.getflowgraph()
+        a = RPythonAnnotator(translator)
+        a.build_types(graph, [])
+        # result should be exactly:
+        self.assertEquals(a.binding(graph.getreturnvar()),
+                          annmodel.SomeTuple([
+                              annmodel.SomeInteger(),
+                              annmodel.SomeObject()
+                              ]))
 
 
 def g(n):

Modified: pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py
==============================================================================
--- pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py	(original)
+++ pypy/trunk/src/pypy/translator/tool/buildpyxmodule.py	Fri May  7 00:24:00 2004
@@ -106,6 +106,10 @@
     name = func.func_name
     funcgraph = space.build_flow(func)
 
+    if not inputargtypes: 
+        source = inspect.getsource(func)
+        base = udir.join(name).newext('.py').write(source) 
+
     if dot:
         from pypy.translator.tool.make_dot import DotGen
         dotgen = DotGen()

Modified: pypy/trunk/src/pypy/translator/transform.py
==============================================================================
--- pypy/trunk/src/pypy/translator/transform.py	(original)
+++ pypy/trunk/src/pypy/translator/transform.py	Fri May  7 00:24:00 2004
@@ -6,7 +6,6 @@
 
 import types
 from pypy.objspace.flow.model import SpaceOperation
-from pypy.annotation.model import SomeValue
 from pypy.translator.annrpython import CannotSimplify
 
 # XXX: Lots of duplicated codes. Fix this!

Modified: pypy/trunk/src/pypy/translator/translator.py
==============================================================================
--- pypy/trunk/src/pypy/translator/translator.py	(original)
+++ pypy/trunk/src/pypy/translator/translator.py	Fri May  7 00:24:00 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