[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