Author: Anton Gulenko <anton.gule...@googlemail.com>
Branch: storage
Changeset: r706:9ef7a4c22818
Date: 2014-03-27 11:52 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/9ef7a4c22818/

Log:    Made _w_self and space fields of Shadows immutable. Added some
        additional __repr__ info to shadows. Fixed finding name of
        Metaclasses. Added some tests for that. Made printing of
        classes/metaclasses more consistent with Smalltalk's asString.

diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -469,10 +469,6 @@
     def repr_content(self):
         return 'len=%d %s' % (self.size(), self.str_content())
     
-    def space(self):
-        assert self.shadow, "Cannot access space without a shadow!"
-        return self.shadow.space
-    
     def fillin(self, space, g_self):
         W_AbstractObjectWithIdentityHash.fillin(self, space, g_self)
         self.w_class = g_self.get_class()
@@ -482,15 +478,12 @@
 
     def guess_classname(self):
         if self.has_class():
-            from shadow import ClassShadow
-            if isinstance(self.w_class.shadow, ClassShadow):
-                return self.w_class.shadow.name or "???"
-            else:
-                # If the shadow of w_class is not yet converted to a 
ClassShadow,
-                # we cannot get the classname, unfortunately. No space 
available.
-                return "?"
+            class_shadow = self.class_shadow(self.w_class.space())
+            # Three question marks, because it would be highly irregular to 
have
+            # an initialized ClassShadow without an initialized name field.
+            return class_shadow.name or "???"
         else:
-            return "??"
+            return "? (no class)"
     
     def invariant(self):
         from spyvm import shadow
@@ -572,6 +565,10 @@
         self.initialize_storage(space, len(pointers))
         self.store_all(space, pointers)
         
+    def space(self):
+        assert self.shadow, "Cannot access space without a shadow!"
+        return self.shadow.space
+        
     def __str__(self):
         if self.has_shadow() and self.shadow.provides_getname:
             return self._get_shadow().getname()
@@ -774,8 +771,8 @@
     def size(self):
         return self._size
 
-    def __str__(self):
-        return self.as_string()
+    def str_content(self):
+        return "'%s'" % self.as_string()
 
     def as_string(self):
         if self.bytes is not None:
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -46,6 +46,8 @@
             name = "w_" + name
             if not name in self.objtable or not self.objtable[name]:
                 self.objtable[name] = specials[idx]
+        # XXX this is kind of hacky, but I don't know where else to get 
Metaclass
+        self.classtable["w_Metaclass"] = self.w_SmallInteger.w_class.w_class
         
     def executable_path(self):
         return self._executable_path[0]
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -11,7 +11,9 @@
     can be attached at run-time to any Smalltalk object.
     """
     _attrs_ = ['_w_self', 'space']
+    _immutable_fields_ = ['_w_self', 'space']
     provides_getname = False
+    repr_classname = "AbstractShadow"
     
     def __init__(self, space, w_self):
         self.space = space
@@ -19,7 +21,12 @@
     def w_self(self):
         return self._w_self
     def getname(self):
-        return repr(self)
+        raise NotImplementedError("Abstract class")
+    def __repr__(self):
+        if self.provides_getname:
+            return "<%s %s>" % (self.repr_classname, self.getname())
+        else:
+            return "<%s>" % self.repr_classname
     
     def fetch(self, n0):
         raise NotImplementedError("Abstract class")
@@ -41,6 +48,7 @@
 
 class ListStorageShadow(AbstractShadow):
     _attrs_ = ['storage']
+    repr_classname = "ListStorageShadow"
     
     def __init__(self, space, w_self, size):
         AbstractShadow.__init__(self, space, w_self)
@@ -61,6 +69,7 @@
 
 class WeakListStorageShadow(AbstractShadow):
     _attrs_ = ['storage']
+    repr_classname = "WeakListStorageShadow"
     
     def __init__(self, space, w_self, size):
         AbstractShadow.__init__(self, space, w_self)
@@ -78,6 +87,7 @@
 class AbstractCachingShadow(ListStorageShadow):
     _immutable_fields_ = ['version?']
     _attrs_ = ['version']
+    repr_classname = "AbstractCachingShadow"
     import_from_mixin(version.VersionMixin)
     version = None
     
@@ -108,13 +118,12 @@
 
     _attrs_ = ["name", "_instance_size", "instance_varsized", "instance_kind",
                 "_s_methoddict", "_s_superclass", "subclass_s"]
-    name = None
+    name = '??'
+    _s_superclass = None
     provides_getname = True
+    repr_classname = "ClassShadow"
     
     def __init__(self, space, w_self):
-        # fields added here should also be in objspace.py:56ff, 300ff
-        self.name = '?'
-        self._s_superclass = None
         self.subclass_s = {}
         AbstractCachingShadow.__init__(self, space, w_self)
 
@@ -168,23 +177,19 @@
                 self.instance_kind = COMPILED_METHOD
             else:
                 raise ClassShadowError("unknown format %d" % (format,))
-        elif n0 == constants.CLASS_NAME_INDEX:
-            self.store_w_name(w_val)
-        elif n0 == self.size() - 1:
-            # In case of Metaclasses, the "instance" class is stored in the 
last field.
-            # TODO - only do this if we are sure this is a Metaclass. Check 
out space.w_Metaclass.
-            if isinstance(w_val, model.W_PointersObject):
-                cl_shadow = w_val.shadow
-                if isinstance(cl_shadow, ClassShadow):
-                    # If we're lucky, it's already a class shadow and we can 
reuse the stored information
-                    if cl_shadow.name:
-                        self.name = "%s class" % cl_shadow.name
-                elif w_val.size() >= constants.CLASS_NAME_INDEX:
-                    # If not, we have to extract the class name
-                    w_classname = w_val.fetch(self.space, 
constants.CLASS_NAME_INDEX)
-                    self.store_w_name(w_classname)
         else:
-            return
+            if self._w_self.w_class == self.space.classtable["w_Metaclass"]:
+                # In case of Metaclasses, the "instance" class is stored in 
the last field.
+                if n0 == self.size() - 1 and isinstance(w_val, 
model.W_PointersObject):
+                    cl_shadow = w_val.as_class_get_shadow(self.space)
+                    self.name = "%s class" % cl_shadow.getname()
+                else:
+                    return
+            elif n0 == constants.CLASS_NAME_INDEX:
+                # In case of regular classes, the name is stored here.
+                self.store_w_name(w_val)
+            else:
+                return
         # Some of the special info has changed -> Switch version.
         self.changed()
     
@@ -255,7 +260,7 @@
         return self._s_superclass
 
     def getname(self):
-        return "%s class" % (self.name or '?',)
+        return self.name or '?'
 
     # _______________________________________________________________
     # Methods for querying the format word, taken from the blue book:
@@ -290,9 +295,6 @@
     # _______________________________________________________________
     # Other Methods
 
-    def __repr__(self):
-        return "<ClassShadow %s>" % (self.name or '?',)
-
     @constant_for_version
     def lookup(self, w_selector):
         look_in_shadow = self
@@ -348,7 +350,8 @@
 
     _immutable_fields_ = ['invalid?', 's_class']
     _attrs_ = ['methoddict', 'invalid', 's_class']
-
+    repr_classname = "MethodDictionaryShadow"
+    
     def __init__(self, space, w_self):
         self.invalid = True
         self.s_class = None
@@ -415,7 +418,8 @@
 
 class AbstractRedirectingShadow(AbstractShadow):
     _attrs_ = ['_w_self_size']
-
+    repr_classname = "AbstractRedirectingShadow"
+    
     def __init__(self, space, w_self):
         AbstractShadow.__init__(self, space, w_self)
         if w_self is not None:
@@ -431,7 +435,8 @@
     __metaclass__ = extendabletype
     _attrs_ = ['_s_sender', '_pc', '_temps_and_stack',
             '_stack_ptr', 'instances_w']
-
+    repr_classname = "ContextPartShadow"
+    
     _virtualizable_ = [
         "_s_sender", "_pc",
         "_temps_and_stack[*]", "_stack_ptr",
@@ -754,7 +759,8 @@
 
 class BlockContextShadow(ContextPartShadow):
     _attrs_ = ['_w_home', '_initialip', '_eargc']
-
+    repr_classname = "BlockContextShadow"
+    
     def __init__(self, space, w_self=None, w_home=None, argcnt=0, initialip=0):
         self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
         creating_w_self = w_self is None
@@ -857,7 +863,8 @@
 
 class MethodContextShadow(ContextPartShadow):
     _attrs_ = ['w_closure_or_nil', '_w_receiver', '_w_method']
-
+    repr_classname = "MethodContextShadow"
+    
     @jit.unroll_safe
     def __init__(self, space, w_self=None, s_method=None, w_receiver=None,
                               arguments=None, s_sender=None, closure=None, 
pc=0):
@@ -1020,7 +1027,8 @@
               "w_compiledin", "version"]
     _immutable_fields_ = ["version?", "_w_self"]
     import_from_mixin(version.VersionMixin)
-
+    repr_classname = "CompiledMethodShadow"
+    
     def __init__(self, w_compiledmethod, space):
         self._w_self = w_compiledmethod
         self.space = space
@@ -1087,6 +1095,7 @@
         return self.bytecode[pc]
 
 class CachedObjectShadow(AbstractCachingShadow):
+    repr_classname = "CachedObjectShadow"
 
     @elidable_for_version
     def fetch(self, n0):
@@ -1098,6 +1107,7 @@
 
 class ObserveeShadow(ListStorageShadow):
     _attrs_ = ['dependent']
+    repr_classname = "ObserveeShadow"
     def __init__(self, space, w_self):
         ListStorageShadow.__init__(self, space, w_self, 0)
         self.dependent = None
diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py
--- a/spyvm/test/test_miniimage.py
+++ b/spyvm/test/test_miniimage.py
@@ -69,32 +69,48 @@
     assert isinstance(w_float_class_name, model.W_BytesObject)
     assert w_float_class_name.bytes == list("Float")
 
-def test_str_w_object():
+# TODO - many of these test would belong in test_model.py
+    
+def test_str_float():
+    assert str(space.wrap_float(3.0)) == "a Float(3.000000)"
+
+def test_str_string():
+    assert str(space.wrap_string('hello')) == "a String('hello')"
+
+def test_str_float():
+    assert str(space.wrap_float(3.0)) == "a Float(3.000000)"
+
+def test_str_class_object():
     w_float_class = get_float_class()
     w_float_class.as_class_get_shadow(space)
-    assert str(w_float_class) == "Float class"
+    assert str(w_float_class) == "Float"
+    
     w_float_class.class_shadow(space)
-    #assert str(w_float_class.getclass(space)) == "a Metaclass" #yes, with 
article
+    assert str(w_float_class.getclass(space)) == "Float class"
+    
     w_float_class.getclass(space).class_shadow(space)
-    #assert str(w_float_class.getclass(space).getclass(space)) == "Metaclass 
class"
+    assert str(w_float_class.getclass(space).getclass(space)) == "Metaclass"
+    
+    w_float_class.getclass(space).getclass(space).class_shadow(space)
+    assert str(w_float_class.getclass(space).getclass(space).getclass(space)) 
== "Metaclass class"
 
 def test_nil_true_false():
     image = get_image()
     w = image.special(constants.SO_NIL)
     w.class_shadow(space)
-    assert str(w) == "a UndefinedObject" #yes, with article
+    assert str(w) == "a UndefinedObject"
     w = image.special(constants.SO_FALSE)
     w.class_shadow(space)
-    assert str(w) == "a False" #yes, with article
+    assert str(w) == "a False"
     w = image.special(constants.SO_TRUE)
     w.class_shadow(space)
-    assert str(w) == "a True" #yes, with article
+    assert str(w) == "a True"
 
 def test_scheduler():
     image = get_image()
     w = image.special(constants.SO_SCHEDULERASSOCIATIONPOINTER)
     w0 = w.fetch(space, 0)
-    assert str(w0) == "Processor"
+    assert str(w0) == "a Symbol('Processor')"
     w0 = w.fetch(space, 1)
     w0.class_shadow(space)
     assert str(w0) == "a ProcessorScheduler"
@@ -106,15 +122,15 @@
         assert str(obj) == expected_name
     image = get_image()
     # w = image.special(constants.SO_BITMAP_CLASS)
-    # assert str(w) == "Bitmap class"
-    test_classname(constants.SO_SMALLINTEGER_CLASS, "SmallInteger class")
-    test_classname(constants.SO_ARRAY_CLASS, "Array class")
-    test_classname(constants.SO_FLOAT_CLASS, "Float class")
-    test_classname(constants.SO_METHODCONTEXT_CLASS, "MethodContext class")
-    test_classname(constants.SO_BLOCKCONTEXT_CLASS, "BlockContext class")
-    test_classname(constants.SO_POINT_CLASS, "Point class")
-    test_classname(constants.SO_LARGEPOSITIVEINTEGER_CLASS, 
"LargePositiveInteger class")
-    test_classname(constants.SO_MESSAGE_CLASS, "Message class")
+    # assert str(w) == "Bitmap"
+    test_classname(constants.SO_SMALLINTEGER_CLASS, "SmallInteger")
+    test_classname(constants.SO_ARRAY_CLASS, "Array")
+    test_classname(constants.SO_FLOAT_CLASS, "Float")
+    test_classname(constants.SO_METHODCONTEXT_CLASS, "MethodContext")
+    test_classname(constants.SO_BLOCKCONTEXT_CLASS, "BlockContext")
+    test_classname(constants.SO_POINT_CLASS, "Point")
+    test_classname(constants.SO_LARGEPOSITIVEINTEGER_CLASS, 
"LargePositiveInteger")
+    test_classname(constants.SO_MESSAGE_CLASS, "Message")
 
     # to be continued
 
@@ -141,8 +157,8 @@
 def test_special_objects0():
     image = get_image()
     w = image.special(constants.SO_DOES_NOT_UNDERSTAND)
-    assert str(w) == "doesNotUnderstand:"
-    assert str(w.getclass(space)) == "Symbol class" # for some strange reason 
not a symbol
+    assert str(w) == "a Symbol('doesNotUnderstand:')"
+    assert str(w.getclass(space)) == "Symbol" # for some strange reason not a 
symbol
 
 
     """
@@ -328,7 +344,7 @@
     assert w_message_cls is interp.space.classtable["w_Message"]
     assert isinstance(w_message_cls, model.W_PointersObject)
     s_message_cls = w_message_cls.as_class_get_shadow(interp.space)
-    assert s_message_cls.getname() == "Message class"
+    assert s_message_cls.getname() == "Message"
     w_message = s_message_cls.new()
     assert isinstance(w_message, model.W_PointersObject)
 
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -10,6 +10,9 @@
 from spyvm.tool.analyseimage import create_image
 from spyvm.interpreter_proxy import VirtualMachine
 
+def print_result(w_result):
+    # This will also print contents of strings/symbols/numbers
+    print w_result.as_repr_string().replace('\r', '\n')
 
 def _run_benchmark(interp, number, benchmark, arg):
     from spyvm.plugins.vmdebugging import stop_ui_process
@@ -46,8 +49,7 @@
     w_result = _run_image(interp)
     t2 = time.time()
     if w_result:
-        if isinstance(w_result, model.W_BytesObject):
-            print w_result.as_string().replace('\r', '\n')
+        print_result(w_result)
         print "took %s seconds" % (t2 - t1)
         return 0
     return -1
@@ -90,10 +92,7 @@
             print e.msg
             return 1
         if w_result:
-            if isinstance(w_result, model.W_BytesObject):
-                print w_result.as_string().replace('\r', '\n')
-            else:
-                print w_result.as_repr_string().replace('\r', '\n')
+            print_result(w_result)
         return 0
     else:
         return _run_benchmark(interp, 0, selector, "")
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to