[pypy-svn] r9752 - in pypy/dist/pypy: annotation interpreter tool translator/test
arigo at codespeak.net
arigo at codespeak.net
Sat Mar 12 22:01:53 CET 2005
Author: arigo
Date: Sat Mar 12 22:01:53 2005
New Revision: 9752
Modified:
pypy/dist/pypy/annotation/bookkeeper.py
pypy/dist/pypy/annotation/model.py
pypy/dist/pypy/annotation/unaryop.py
pypy/dist/pypy/interpreter/gateway.py
pypy/dist/pypy/interpreter/lazymodule.py
pypy/dist/pypy/tool/cache.py
pypy/dist/pypy/translator/test/test_annrpython.py
Log:
Added the _freeze_() protocol to help the annotator decide if something is a pre-built constant or a SomeInstance (i.e. holds mutable state). The method _freeze_() is also a good place for the objects to perform last-minute initialization, e.g. for LazyModule objects.
Added a test for _freeze_().
New method bookkeeper.warning() for all warning-issuing situations of the annotator.
Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py (original)
+++ pypy/dist/pypy/annotation/bookkeeper.py Sat Mar 12 22:01:53 2005
@@ -4,6 +4,7 @@
from types import FunctionType, ClassType, MethodType
from types import BuiltinMethodType
+from pypy.tool.ansi_print import ansi_print
from pypy.annotation.model import *
from pypy.annotation.classdef import ClassDef
from pypy.interpreter.miscutils import getthreadlocals
@@ -29,6 +30,7 @@
self.userclasseslist = []# userclasses.keys() in creation order
self.cachespecializations = {}
self.pbccache = {}
+ self.pbctypes = {}
# import ordering hack
global BUILTIN_ANALYZERS
from pypy.annotation.builtin import BUILTIN_ANALYZERS
@@ -64,6 +66,9 @@
try:
return self.userclasses[cls]
except KeyError:
+ if cls in self.pbctypes:
+ self.warning("%r gets a ClassDef, but is the type of some PBC"
+ % (cls,))
cdef = ClassDef(cls, self)
self.userclasses[cls] = cdef
self.userclasseslist.append(cdef)
@@ -94,9 +99,8 @@
elif callable(x) or isinstance(x, staticmethod): # XXX
# maybe 'x' is a method bound to a not-yet-frozen cache?
# fun fun fun.
- if (hasattr(x, 'im_self') and isinstance(x.im_self, Cache)
- and not x.im_self.frozen):
- x.im_self.freeze()
+ if hasattr(x, 'im_self') and hasattr(x.im_self, '_freeze_'):
+ x.im_self._freeze_()
if hasattr(x, '__self__') and x.__self__ is not None:
s_self = self.immutablevalue(x.__self__)
try:
@@ -107,9 +111,18 @@
return self.getpbc(x)
elif hasattr(x, '__class__') \
and x.__class__.__module__ != '__builtin__':
- if isinstance(x, Cache) and not x.frozen:
- x.freeze()
- return self.getpbc(x)
+ # user-defined classes can define a method _freeze_(), which
+ # is called when a prebuilt instance is found. If the method
+ # returns True, the instance is considered immutable and becomes
+ # a SomePBC(). Otherwise it's just SomeInstance().
+ frozen = hasattr(x, '_freeze_') and x._freeze_()
+ if frozen:
+ return self.getpbc(x)
+ else:
+ clsdef = self.getclassdef(x.__class__)
+ for attr in x.__dict__:
+ clsdef.add_source_for_attribute(attr, x)
+ return SomeInstance(clsdef)
elif x is None:
return self.getpbc(None)
else:
@@ -124,15 +137,22 @@
return self.pbccache[x]
except KeyError:
result = SomePBC({x: True}) # pre-built inst
- clsdef = self.getclassdef(new_or_old_class(x))
- for attr in getattr(x, '__dict__', {}):
- clsdef.add_source_for_attribute(attr, x)
+ #clsdef = self.getclassdef(new_or_old_class(x))
+ #for attr in getattr(x, '__dict__', {}):
+ # clsdef.add_source_for_attribute(attr, x)
self.pbccache[x] = result
+ cls = new_or_old_class(x)
+ if cls not in self.pbctypes:
+ self.pbctypes[cls] = True
+ if cls in self.userclasses:
+ self.warning("making some PBC of type %r, which has "
+ "already got a ClassDef" % (cls,))
return result
def valueoftype(self, t):
"""The most precise SomeValue instance that contains all
objects of type t."""
+ assert isinstance(t, (type, ClassType))
if t is bool:
return SomeBool()
elif t is int:
@@ -142,8 +162,7 @@
elif t is list:
return SomeList(factories={})
# can't do dict, tuple
- elif isinstance(t, (type, ClassType)) and \
- t.__module__ != '__builtin__':
+ elif t.__module__ != '__builtin__':
classdef = self.getclassdef(t)
return SomeInstance(classdef)
else:
@@ -246,6 +265,13 @@
def whereami(self):
return self.annotator.whereami(self.position_key)
+ def warning(self, msg):
+ try:
+ pos = self.whereami()
+ except AttributeError:
+ pos = '?'
+ ansi_print("*** WARNING: [%s] %s" % (pos, msg), esc="31") # RED
+
def specialize_by_key(self, thing, key, name=None):
key = thing, key
try:
Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py (original)
+++ pypy/dist/pypy/annotation/model.py Sat Mar 12 22:01:53 2005
@@ -32,7 +32,6 @@
import pypy
from pypy.annotation.pairtype import pair, extendabletype
from pypy.objspace.flow.model import Constant
-from pypy.tool.cache import Cache
import inspect
Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py (original)
+++ pypy/dist/pypy/annotation/unaryop.py Sat Mar 12 22:01:53 2005
@@ -3,7 +3,6 @@
"""
from types import FunctionType
-from pypy.tool.ansi_print import ansi_print
from pypy.interpreter.argument import Arguments
from pypy.annotation.pairtype import pair
from pypy.annotation.model import SomeObject, SomeInteger, SomeBool
@@ -90,8 +89,7 @@
def call(obj, args):
#raise Exception, "cannot follow call_args%r" % ((obj, args),)
- ansi_print("*** WARNING: [%s] cannot follow call(%r, %r)" %
- (getbookkeeper().whereami(), obj, args), esc="31") # RED
+ getbookkeeper().warning("cannot follow call(%r, %r)" % (obj, args))
return SomeObject()
class __extend__(SomeInteger):
@@ -238,17 +236,14 @@
for c in pbc.prebuiltinstances:
if hasattr(c, attr):
# force the attribute to be considered on the class
- classdef = bookkeeper.getclassdef(new_or_old_class(c))
- classdef.find_attribute(attr).getvalue()
+ ##classdef = bookkeeper.getclassdef(new_or_old_class(c))
+ ##classdef.find_attribute(attr).getvalue()
# but only return the more precise result getattr(c, attr)
actuals.append(immutablevalue(getattr(c, attr)))
return unionof(*actuals)
def setattr(pbc, s_attr, s_value):
- #raise Exception, "oops!"
- ansi_print("*** WARNING: [%s] setattr not wanted on %r" %
- (getbookkeeper().whereami(), pbc), esc="31") # RED
- pass
+ getbookkeeper().warning("setattr not wanted on %r" % (pbc,))
def call(pbc, args):
bookkeeper = getbookkeeper()
@@ -269,9 +264,9 @@
d = {}
for func, value in pbc.prebuiltinstances.items():
if isinstance(func, FunctionType):
- if isclassdef(value):
- print ("!!! rebinding an already bound"
- " method %r with %r" % (func, value))
+ if isclassdef(value):
+ getbookkeeper().warning("rebinding an already bound "
+ "method %r with %r" % (func, value))
d[func] = classdef
elif isinstance(func, staticmethod):
d[func.__get__(43)] = value
Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py (original)
+++ pypy/dist/pypy/interpreter/gateway.py Sat Mar 12 22:01:53 2005
@@ -522,6 +522,9 @@
appcaller.get_function = get_function
return appcaller
+ def _freeze_(self):
+ return True # hint for the annotator: applevel instances are constants
+
## XXX experimental code using geninterplevel
class applevelinterp(applevel):
Modified: pypy/dist/pypy/interpreter/lazymodule.py
==============================================================================
--- pypy/dist/pypy/interpreter/lazymodule.py (original)
+++ pypy/dist/pypy/interpreter/lazymodule.py Sat Mar 12 22:01:53 2005
@@ -54,6 +54,12 @@
self.lazy = False
return self.w_dict
+ def _freeze_(self):
+ self.getdict()
+ # hint for the annotator: Modules can hold state, so they are
+ # not constant
+ return False
+
def buildloaders(cls):
""" NOT_RPYTHON """
if not hasattr(cls, 'loaders'):
Modified: pypy/dist/pypy/tool/cache.py
==============================================================================
--- pypy/dist/pypy/tool/cache.py (original)
+++ pypy/dist/pypy/tool/cache.py Sat Mar 12 22:01:53 2005
@@ -32,4 +32,10 @@
getorbuild._specialize_ = "location"
def freeze(self):
- del self.frozen
+ try:
+ del self.frozen
+ except AttributeError:
+ pass
+ return True
+
+ _freeze_ = freeze
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 Sat Mar 12 22:01:53 2005
@@ -594,6 +594,25 @@
assert isinstance(s, annmodel.SomeInstance)
assert s.knowntype is snippet.Exc
+ def test_freeze_protocol(self):
+ class Stuff:
+ def __init__(self, flag):
+ self.called = False
+ self.flag = flag
+ def _freeze_(self):
+ self.called = True
+ return self.flag
+ myobj = Stuff(True)
+ a = RPythonAnnotator()
+ s = a.build_types(lambda: myobj, [])
+ assert myobj.called
+ assert s == annmodel.SomePBC({myobj: True})
+ myobj = Stuff(False)
+ a = RPythonAnnotator()
+ s = a.build_types(lambda: myobj, [])
+ assert myobj.called
+ assert s == annmodel.SomeInstance(a.bookkeeper.getclassdef(Stuff))
+
def g(n):
return [0,1,2,n]
More information about the Pypy-commit
mailing list