[pypy-svn] r19984 - pypy/branch/somepbc-refactoring/pypy/annotation
pedronis at codespeak.net
pedronis at codespeak.net
Thu Nov 17 19:03:32 CET 2005
Author: pedronis
Date: Thu Nov 17 19:03:29 2005
New Revision: 19984
Modified:
pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py
pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py
Log:
(arigo, pedronis)
started refactoring ClassDef setup logic in preparation to move it to ClassDesc and to add support for synthetic ClassDefs
Modified: pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py (original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py Thu Nov 17 19:03:29 2005
@@ -12,7 +12,7 @@
SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, \
SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
SomeList, SomeObject
-from pypy.annotation.classdef import ClassDef
+from pypy.annotation.classdef import ClassDef, ConstantSource
from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF
from pypy.annotation import description
@@ -359,7 +359,7 @@
self.seen_mutable[x] = True
self.event('mutable', x)
for attr in x.__dict__:
- clsdef.add_source_for_attribute(attr, x) # can trigger reflowing
+ clsdef.add_source_for_attribute(attr, ConstantSource(self, x, None)) # can trigger reflowing
result = SomeInstance(clsdef)
elif x is None:
return s_None
Modified: pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py (original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py Thu Nov 17 19:03:29 2005
@@ -65,6 +65,23 @@
# same name in all subclasses of A, if any. (Parent class attributes can
# be visible in reads from instances of subclasses.)
+class ConstantSource:
+
+ def __init__(self, bookkeeper, obj, classdef=None):
+ self.bookkeeper = bookkeeper
+ self.obj = obj
+ self.classdef = classdef
+
+ def s_read_attribute(self, name):
+ s_value = self.bookkeeper.immutablevalue(
+ self.obj.__dict__[name])
+ if self.classdef:
+ s_value = s_value.bindcallables(self.classdef)
+ return s_value
+
+ def is_instance_level(self):
+ return self.classdef is None
+
class Attribute:
# readonly-ness
@@ -76,17 +93,13 @@
def __init__(self, name, bookkeeper):
self.name = name
self.bookkeeper = bookkeeper
- # XXX a SomeImpossibleValue() constant? later!!
self.s_value = SomeImpossibleValue()
self.readonly = True
self.read_locations = {}
- def add_constant_source(self, source, classdef):
- s_value = self.bookkeeper.immutablevalue(
- source.__dict__[self.name])
- if classdef:
- s_value = s_value.bindcallables(classdef)
- else:
+ def add_constant_source(self, source):
+ s_value = source.s_read_attribute(self.name)
+ if source.is_instance_level():
# a prebuilt instance source forces readonly=False, see above
self.readonly = False
s_new_value = unionof(self.s_value, s_value)
@@ -141,17 +154,31 @@
#self.instantiation_locations = {}
self.cls = cls
self.subdefs = {}
- self.attr_sources = {} # {name: {constant_object: classdef_or_None}}
+ self.attr_sources = {} # {name: {constant-source: True}}
base = object
- mixeddict = {}
- sources = {}
+
+
+ classsources = {}
+
baselist = list(cls.__bases__)
baselist.reverse()
self.also_Exception_subclass = False
if Exception in baselist and len(baselist)>1: # special-case
baselist.remove(Exception)
- mixeddict['__init__'] = Exception.__init__.im_func
+ classsources['__init__'] = ConstantSource(bookkeeper, Exception, self)
self.also_Exception_subclass = True
+
+ def add_sources_for_class(cls):
+ source = ConstantSource(bookkeeper, cls, self)
+ for name, value in cls.__dict__.items():
+ # ignore some special attributes
+ if name.startswith('_') and not isinstance(value, FunctionType):
+ continue
+ # for debugging
+ if isinstance(value, FunctionType):
+ if not hasattr(value, 'class_'):
+ value.class_ = self.cls # remember that this is really a method
+ classsources[name] = source
for b1 in baselist:
if b1 is object:
@@ -159,14 +186,13 @@
if getattr(b1, '_mixin_', False):
assert b1.__bases__ == () or b1.__bases__ == (object,), (
"mixin class %r should have no base" % (b1,))
- mixeddict.update(b1.__dict__)
- for name in b1.__dict__:
- sources[name] = b1
+ add_sources_for_class(b1)
else:
assert base is object, ("multiple inheritance only supported "
"with _mixin_: %r" % (cls,))
base = b1
- mixeddict.update(cls.__dict__)
+
+ add_sources_for_class(cls)
self.basedef = bookkeeper.getuniqueclassdef(base)
if self.basedef:
@@ -174,7 +200,7 @@
# pass some data to the setup() method, which must be called
# after the __init__()
- self.sources_from_the_class = mixeddict, sources
+ self.sources_from_the_class = classsources
# forced attributes
if cls in FORCE_ATTRIBUTES_INTO_CLASSES:
@@ -185,20 +211,14 @@
def setup(self):
# collect the (supposed constant) class attributes
cls = self.cls
- d, sources = self.sources_from_the_class
+ sources = self.sources_from_the_class
del self.sources_from_the_class # setup() shouldn't be called twice
- for name, value in d.items():
- # ignore some special attributes
- if name.startswith('_') and not isinstance(value, FunctionType):
- continue
- if isinstance(value, FunctionType):
- if not hasattr(value, 'class_'):
- value.class_ = cls # remember that this is really a method
- self.add_source_for_attribute(name, sources.get(name, cls), self)
+ for name, source in sources.items():
+ self.add_source_for_attribute(name, source)
if self.bookkeeper:
self.bookkeeper.event('classdef_setup', self)
- def add_source_for_attribute(self, attr, source, clsdef=None):
+ def add_source_for_attribute(self, attr, source):
"""Adds information about a constant source for an attribute.
"""
sources = self.attr_sources.setdefault(attr, {})
@@ -207,7 +227,7 @@
# the Attribute() exists already for this class (or a parent)
attrdef = cdef.attrs[attr]
s_prev_value = attrdef.s_value
- attrdef.add_constant_source(source, clsdef)
+ attrdef.add_constant_source(source)
# we should reflow from all the reader's position,
# but as an optimization we try to see if the attribute
# has really been generalized
@@ -216,18 +236,18 @@
return
else:
# remember the source in self.attr_sources
- sources[source] = clsdef
+ sources[source] = True
# register the source in any Attribute found in subclasses,
# to restore invariant (III)
# NB. add_constant_source() may discover new subdefs but the
# right thing will happen to them because self.attr_sources
# was already updated
- if clsdef is not None:
+ if not source.is_instance_level():
for subdef in self.getallsubdefs():
if attr in subdef.attrs:
attrdef = subdef.attrs[attr]
s_prev_value = attrdef.s_value
- attrdef.add_constant_source(source, clsdef)
+ attrdef.add_constant_source(source)
if attrdef.s_value != s_prev_value:
attrdef.mutated(subdef) # reflow from all read positions
@@ -299,9 +319,9 @@
# invariant (III)
for superdef in self.getmro():
if attr in superdef.attr_sources:
- for source, classdef in superdef.attr_sources[attr].items():
- if classdef is not None:
- constant_sources[source] = classdef
+ for source in superdef.attr_sources[attr]:
+ if not source.is_instance_level():
+ constant_sources[source] = True
# create the Attribute and do the generalization asked for
newattr = Attribute(attr, self.bookkeeper)
@@ -318,8 +338,8 @@
# add the values of the pending constant attributes
# completes invariants (II) and (III)
- for source, classdef in constant_sources.items():
- newattr.add_constant_source(source, classdef)
+ for source in constant_sources:
+ newattr.add_constant_source(source)
# reflow from all read positions
newattr.mutated(self)
@@ -412,7 +432,7 @@
def check_attr_here(self, name):
if name in self.cls.__dict__:
# oups! new attribute showed up
- self.add_source_for_attribute(name, self.cls, self)
+ self.add_source_for_attribute(name, ConstantSource(self.bookkeeper, self.cls, self))
# maybe it also showed up in some subclass?
for subdef in self.getallsubdefs():
if subdef is not self:
More information about the Pypy-commit
mailing list