Author: Anton Gulenko <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit