Author: Spenser Bauman <saba...@gmail.com>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to