Author: Spenser Bauman <[email protected]>
Branch: value-classes
Changeset: r87255:7c0752bdace0
Date: 2016-09-20 12:07 -0400
http://bitbucket.org/pypy/pypy/changeset/7c0752bdace0/
Log: Start working on _value_class_ annotation
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -62,6 +62,9 @@
"""Raised when the _immutable_ or _immutable_fields_ hints are
not consistent across a class hierarchy."""
+class ValueClassConflictError(Exception):
+ """Raise when the _value_class_ hints are not consistent across
+ the class heirarchy"""
def getclassrepr(rtyper, classdef):
if classdef is None:
@@ -517,6 +520,7 @@
if hints is None:
hints = {}
hints = self._check_for_immutable_hints(hints)
+ hints = self._check_for_value_class_hints(hints)
kwds = {}
if self.gcflavor == 'gc':
kwds['rtti'] = True
@@ -560,6 +564,38 @@
hints['immutable_fields'] = accessor
return hints
+ def _check_for_value_class_hints(self, hints):
+ """Look for value class hints in the class heirarchy to extract the
proper
+ hints and ensure consistency of the _value_class_ annotation. This is
+ mostly equivalent to _check_for_immutable_hints except that
+ _value_class_=True requires _immutable_=True as well."""
+ hints = hints.copy()
+ classdesc = self.classdef.classdesc
+ value_class = classdesc.get_param('_value_class_', inherit=False)
+ if value_class is None:
+ if classdesc.get_param('_value_class_', inherit=True):
+ raise ValueClassConflictError(
+ "class %r inherits from its parent _value_class_=True, "
+ "so it should also declare _value_class_=True" % (
+ self.classdef,))
+ elif value_class is not True:
+ raise TyperError(
+ "class %r: _value_class_ = something else than True" % (
+ self.classdef,))
+ elif not hints.get('immutable', False):
+ raise ValueClassConflictError(
+ "class %r: _value_class_ = True requires that "
+ "_immutable_ = True as well")
+ else:
+ # Value classes may only be subclasses of other value classes
+ basedesc = classdesc.basedesc
+ if basedesc and not basedesc.get_param('_value_class_', False):
+ raise ValueClassConflictError(
+ "class %r: _value_class_ = True, but its parent "
+ "class %r does not")
+ hints['value_class'] = True
+ return hints
+
def __repr__(self):
if self.classdef is None:
clsname = 'object'
diff --git a/rpython/rtyper/test/test_rclass.py
b/rpython/rtyper/test/test_rclass.py
--- a/rpython/rtyper/test/test_rclass.py
+++ b/rpython/rtyper/test/test_rclass.py
@@ -1305,3 +1305,53 @@
def f():
return a.next.next.next.next is not None
assert self.interpret(f, []) == True
+
+ def test_value_class(self):
+
+ class I(object):
+ _immutable_ = True
+ _value_class_ = True
+
+ def __init__(self, v):
+ self.v = v
+
+ i = I(3)
+ def f():
+ return i.v
+
+ t, typer, graph = self.gengraph(f, [], backendopt=True)
+ assert summary(graph) == {}
+
+ def test_value_class_not_immutable(self):
+ from rpython.rtyper.rclass import ValueClassConflictError
+
+ class I(object):
+ _value_class_ = True
+
+ def __init__(self, v):
+ self.v = v
+
+ i = I(3)
+ def f():
+ return i.v
+
+ py.test.raises(ValueClassConflictError, self.gengraph, f, [])
+
+ def test_value_class_subclass_not_value_class(self):
+ from rpython.rtyper.rclass import ValueClassConflictError
+
+ class Base(object):
+ _immutable_ = True
+
+ class I(Base):
+ _immutable_ = True
+ _value_class_ = True
+
+ def __init__(self, v):
+ self.v = v
+
+ i = I(3)
+ def f():
+ return i.v
+
+ py.test.raises(ValueClassConflictError, self.gengraph, f, [])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit