[pypy-svn] r9590 - in pypy/dist/pypy: annotation annotation/test translator/test
pedronis at codespeak.net
pedronis at codespeak.net
Wed Mar 2 19:40:07 CET 2005
Author: pedronis
Date: Wed Mar 2 19:40:07 2005
New Revision: 9590
Modified:
pypy/dist/pypy/annotation/classdef.py
pypy/dist/pypy/annotation/model.py
pypy/dist/pypy/annotation/test/test_model.py
pypy/dist/pypy/annotation/unaryop.py
pypy/dist/pypy/translator/test/snippet.py
pypy/dist/pypy/translator/test/test_annrpython.py
Log:
don't bump classdef revision number if only a fresher revision in an attribute is involved,
notice that we still reflow even in this case.
contains logic modified to let caller distinguish this situation, RevDiff (a false value)
is returned if the only reason for a false contains relationship is rev numbers.
without these changes the new test analysing make_eo would recurse infinititely.
Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py (original)
+++ pypy/dist/pypy/annotation/classdef.py Wed Mar 2 19:40:07 2005
@@ -4,7 +4,7 @@
from __future__ import generators
from types import FunctionType
-from pypy.annotation.model import SomeImpossibleValue, unionof
+from pypy.annotation.model import SomeImpossibleValue, unionof, RevDiff
class Attribute:
@@ -118,12 +118,25 @@
def _generalize_attr(self, attr, s_value):
# first remove the attribute from subclasses -- including us!
subclass_attrs = []
+ was_here = attr in self.attrs
for subdef in self.getallsubdefs():
if attr in subdef.attrs:
subclass_attrs.append(subdef.attrs[attr])
del subdef.attrs[attr]
- # bump the revision number of this class and all subclasses
- subdef.revision += 1
+
+ bump = True
+ # don't bump if the only cause is rev diff discrepancies
+ if was_here and len(subclass_attrs) == 1 and s_value is not None:
+ old_attr = subclass_attrs[0]
+ wasgeneralenough = old_attr.s_value.contains(s_value)
+ assert not wasgeneralenough
+ if wasgeneralenough is RevDiff:
+ bump = False
+
+ if bump:
+ # bump the revision number of this class and all subclasses
+ for subdef in self.getallsubdefs():
+ subdef.revision += 1
# do the generalization
newattr = Attribute(attr, self.bookkeeper)
@@ -140,11 +153,16 @@
def generalize_attr(self, attr, s_value=None):
# if the attribute exists in a superclass, generalize there.
+ found = 0
for clsdef in self.getmro():
if attr in clsdef.attrs:
- clsdef._generalize_attr(attr, s_value)
- else:
+ if found == 0:
+ clsdef._generalize_attr(attr, s_value)
+ found += 1
+ if found == 0:
self._generalize_attr(attr, s_value)
+ else:
+ assert found == 1, "generalization itself should prevent this"
def about_attribute(self, name):
for cdef in self.getmro():
Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py (original)
+++ pypy/dist/pypy/annotation/model.py Wed Mar 2 19:40:07 2005
@@ -39,6 +39,31 @@
DEBUG = True # set to False to disable recording of debugging information
+# weak false, for contains in the case of SomeInstance revision differences
+
+class _RevDiff(object):
+ def __nonzero__(self):
+ return False
+
+ def __repr__(self):
+ return "RevDiff"
+
+RevDiff = _RevDiff()
+
+# False contains_and RevDiff = False
+# RevDiff contains_and False = False
+# RevDiff contains_and True = RevDiff
+# True contains_and RevDiff = RevDiff
+
+def contains_and(*args):
+ if False in args:
+ return False
+ if RevDiff in args:
+ return RevDiff
+ assert args == (True,) * len(args)
+ return True
+
+
class SomeObject:
"""The set of all objects. Each instance stands
for an arbitrary object about which nothing is known."""
@@ -77,6 +102,7 @@
return self.hom_contains(s_union)
# default hom_contains, hom_contains can assume self.__class__ == other.__class__
+ # IMPORTANT: use contains_and or equivalent in here
def hom_contains(self, other):
return pair(self, other).union() == self
@@ -153,9 +179,9 @@
self.step = step
def hom_contains(self, other):
- return (self.start.contains(other.start) and
- self.stop.contains(other.stop) and
- self.step.contains(other.step))
+ return contains_and(self.start.contains(other.start),
+ self.stop.contains(other.stop),
+ self.step.contains(other.step))
class SomeTuple(SomeObject):
@@ -174,11 +200,7 @@
other_items = other.items
if len(self.items) != len(self.items):
return False
- for i1, i2 in zip(self_items, other_items):
- if not i1.contains(i2):
- return False
- return True
-
+ return contains_and(*[i1.contains(i2) for i1,i2 in zip(self_items, other_items)])
class SomeDict(SomeObject):
@@ -190,7 +212,8 @@
self.s_value = s_value
def hom_contains(self, other):
- return self.s_key.contains(other.s_key) and self.s_value.contains(other.s_value)
+ return contains_and(self.s_key.contains(other.s_key),
+ self.s_value.contains(other.s_value))
class SomeIterator(SomeObject):
@@ -215,7 +238,10 @@
def hom_contains(self, other):
if self.classdef is other.classdef:
- return self.revision >= other.revision
+ if self.revision >= other.revision:
+ return True
+ else:
+ return RevDiff
return self.classdef.commonbase(other.classdef) is self.classdef
def new_or_old_class(c):
@@ -282,7 +308,11 @@
self.s_self = s_self
def hom_contains(self, other):
- return self.analyser == other.analyser and (not self.s_self or self.s_self.contains(other.s_self))
+ if self.analyser != other.analyser:
+ return False
+ if self.s_self is None:
+ return other.s_self is None
+ return self.s_self.contains(other.s_self)
class SomeImpossibleValue(SomeObject):
Modified: pypy/dist/pypy/annotation/test/test_model.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_model.py (original)
+++ pypy/dist/pypy/annotation/test/test_model.py Wed Mar 2 19:40:07 2005
@@ -31,7 +31,108 @@
(s4,s4), (s4,s6),
(s5,s4), (s5,s5), (s5,s6),
(s6,s6),
- (s7,s6), (s7, s7)])
+ (s7,s6), (s7,s7)])
+
+
+def test_contains_more():
+ from pypy.annotation import bookkeeper
+ bk = bookkeeper.Bookkeeper(None)
+ class C:
+ pass
+ C_classdef = bk.getclassdef(C)
+ si1 = SomeInstance(C_classdef)
+ C_classdef.revision += 1
+ si2 = SomeInstance(C_classdef)
+
+ assert s1.contains(si1)
+ assert si1.contains(si1)
+ assert si1.contains(s6)
+
+ assert si2.contains(si1)
+ assert not si1.contains(si2)
+ assert si1.contains(si2) is RevDiff
+
+ # dicts
+
+ sd1 = SomeDict({}, SomeString(), s1)
+ sd6 = SomeDict({}, SomeString(), s6)
+ sdi1 = SomeDict({}, SomeString(), si1)
+ sdi2 = SomeDict({}, SomeString(), si2)
+ sdi3 = SomeDict({}, SomeInteger(), si1)
+
+ assert sd1.contains(sdi1)
+ assert sdi1.contains(sdi1)
+ assert sdi1.contains(sd6)
+
+ assert sdi2.contains(sdi1)
+ assert not sdi1.contains(sdi2)
+ assert sdi1.contains(sdi2) is RevDiff
+
+ assert not sdi1.contains(sdi3)
+ assert sdi1.contains(sdi3) is False
+ assert not sdi3.contains(sdi1)
+ assert sdi3.contains(sdi1) is False
+
+ sdx = SomeDict({}, si1, SomeString())
+ sdy = SomeDict({}, si2, SomeString())
+
+ assert sdy.contains(sdx)
+ assert not sdx.contains(sdy)
+ assert sdx.contains(sdy) is RevDiff
+
+ sdz = SomeDict({}, si1, SomeInteger())
+
+ assert not sdz.contains(sdx)
+ assert not sdx.contains(sdz)
+ assert sdz.contains(sdx) is False
+ assert sdx.contains(sdz) is False
+
+ # tuples
+
+ st1 = SomeTuple((SomeString(), s1))
+ st6 = SomeTuple((SomeString(), s6))
+ sti1 = SomeTuple((SomeString(), si1))
+ sti2 = SomeTuple((SomeString(), si2))
+ sti3 = SomeTuple((SomeInteger(), si1))
+
+ assert st1.contains(sti1)
+ assert sti1.contains(sti1)
+ assert sti1.contains(st6)
+
+ assert sti2.contains(sti1)
+ assert not sti1.contains(sti2)
+ assert sti1.contains(sti2) is RevDiff
+
+ assert not sti1.contains(sti3)
+ assert sti1.contains(sti3) is False
+ assert not sti3.contains(sti1)
+ assert sti3.contains(sti1) is False
+
+ stx = SomeTuple((si1, SomeString()))
+ sty = SomeTuple((si2, SomeString()))
+
+ assert sty.contains(stx)
+ assert not stx.contains(sty)
+ assert stx.contains(sty) is RevDiff
+
+ stz = SomeTuple((si1, SomeInteger()))
+
+ assert not stz.contains(stx)
+ assert not stx.contains(stz)
+ assert stz.contains(stx) is False
+ assert stx.contains(stz) is False
+
+ C_classdef.revision += 1
+ si3 = SomeInstance(C_classdef)
+
+ sti12 = SomeTuple((si1,si2))
+ sti23 = SomeTuple((si2,si3))
+
+ assert sti23.contains(sti12)
+ assert not sti12.contains(sti23)
+ assert sti12.contains(sti23) is RevDiff
+
+
def test_union():
assert ([unionof(s,t) for s in slist for t in slist] ==
Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py (original)
+++ pypy/dist/pypy/annotation/unaryop.py Wed Mar 2 19:40:07 2005
@@ -194,6 +194,7 @@
# if the attrdef is new, this must fail
if attrdef.getvalue().contains(s_value):
return
+
# create or update the attribute in clsdef
clsdef.generalize_attr(attr, s_value)
raise BlockedInference
Modified: pypy/dist/pypy/translator/test/snippet.py
==============================================================================
--- pypy/dist/pypy/translator/test/snippet.py (original)
+++ pypy/dist/pypy/translator/test/snippet.py Wed Mar 2 19:40:07 2005
@@ -913,3 +913,46 @@
def propagation_of_fresh_instances_through_attrs(x):
e = EC()
e.enter(x)
+
+# same involving recursion
+
+
+class R:
+ def __init__(self, n):
+ if n>0:
+ self.r = R(n-1)
+ else:
+ self.r = None
+ self.n = n
+ if self.r:
+ self.m = self.r.n
+ else:
+ self.m = -1
+
+def make_r(n):
+ return R(n)
+
+class B:
+ pass
+
+class Even(B):
+ def __init__(self,n):
+ if n > 0:
+ self.x = [Odd(n-1)]
+ self.y = self.x[0].x
+ else:
+ self.x = []
+ self.y = []
+
+class Odd(B):
+ def __init__(self,n):
+ self.x = [Even(n-1)]
+ self.y = self.x[0].x
+
+def make_eo(n):
+ if n%2 == 0:
+ return Even(n)
+ else:
+ return Odd(n)
+
+
Modified: pypy/dist/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_annrpython.py (original)
+++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Mar 2 19:40:07 2005
@@ -530,7 +530,29 @@
a = RPythonAnnotator()
s = a.build_types(snippet.propagation_of_fresh_instances_through_attrs, [int])
assert s is not None
+
+ def test_propagation_of_fresh_instances_through_attrs_rec_0(self):
+ a = RPythonAnnotator()
+ s = a.build_types(snippet.make_r, [int])
+ assert s.knowntype == snippet.R
+ Rdef = a.getuserclasses()[snippet.R]
+ assert Rdef.attrs['r'].s_value.knowntype == snippet.R
+ assert Rdef.attrs['n'].s_value.knowntype == int
+ assert Rdef.attrs['m'].s_value.knowntype == int
+
+ def test_propagation_of_fresh_instances_through_attrs_rec_eo(self):
+ a = RPythonAnnotator()
+ s = a.build_types(snippet.make_eo, [int])
+ assert s.knowntype == snippet.B
+ Even_def = a.getuserclasses()[snippet.Even]
+ Odd_def = a.getuserclasses()[snippet.Odd]
+ assert Even_def.attrs['x'].s_value.s_item.knowntype == snippet.Odd
+ assert Even_def.attrs['y'].s_value.s_item.knowntype == snippet.Even
+ assert Odd_def.attrs['x'].s_value.s_item.knowntype == snippet.Even
+ assert Odd_def.attrs['y'].s_value.s_item.knowntype == snippet.Odd
+
+
def g(n):
return [0,1,2,n]
More information about the Pypy-commit
mailing list