[pypy-svn] r47863 - in pypy/dist/pypy/lang/smalltalk: . test

arigo at codespeak.net arigo at codespeak.net
Wed Oct 24 22:24:09 CEST 2007


Author: arigo
Date: Wed Oct 24 22:24:08 2007
New Revision: 47863

Added:
   pypy/dist/pypy/lang/smalltalk/mirror.py   (contents, props changed)
Modified:
   pypy/dist/pypy/lang/smalltalk/classtable.py
   pypy/dist/pypy/lang/smalltalk/fakeimage.py
   pypy/dist/pypy/lang/smalltalk/interpreter.py
   pypy/dist/pypy/lang/smalltalk/model.py
   pypy/dist/pypy/lang/smalltalk/primitives.py
   pypy/dist/pypy/lang/smalltalk/squeakimage.py
   pypy/dist/pypy/lang/smalltalk/test/test_classtable.py
   pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py
   pypy/dist/pypy/lang/smalltalk/test/test_model.py
   pypy/dist/pypy/lang/smalltalk/test/test_primitives.py
Log:
(cfbolz, arigo)

Big refactoring.  Every Smalltalk object used as the class of another
Smalltalk object now gets a "mirror" object that only exists in the
interpreter.  The mirror decodes the mind-bogglingly complicated
bitfields and the method dict and stores it in nicely readable RPython
fields.  The internal class field of each Smalltalk object is now
poiting to the mirror directly.  This changes mostly everything done so
far, but should be much more future-proof and cleaner from various
points of view.



Modified: pypy/dist/pypy/lang/smalltalk/classtable.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/classtable.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/classtable.py	Wed Oct 24 22:24:08 2007
@@ -1,69 +1,89 @@
-from pypy.lang.smalltalk.model import \
-     W_Class, W_MetaClass, W_SmallInteger, POINTERS, BYTES
+from pypy.lang.smalltalk import mirror
+
+def bootstrap_classmirror(instsize, m_superclass=None, m_metaclass=None,
+                          name='?', format=mirror.POINTERS, varsized=False):
+    from pypy.lang.smalltalk import model
+    w_class = model.W_Object()     # a dummy placeholder for testing
+    m = mirror.ClassMirror(w_class)
+    m.methoddict = {}
+    m.m_superclass = m_superclass
+    m.m_metaclass = m_metaclass
+    m.name = name
+    m.instance_size = instsize
+    m.instance_kind = format
+    m.instance_varsized = varsized or format != mirror.POINTERS
+    m.invalid = False
+    mirror.mirrorcache.cache[w_class] = m
+    return m
 
 # ___________________________________________________________________________
 # Core Bootstrapping Objects
 
 classtable = {}
 def create_classtable():
-    def define_core_cls(clsnm, clsobj):
-        clsobj.name = clsnm
-        classtable[clsnm] = clsobj
-        globals()[clsnm] = clsobj
-        return clsobj
+    def define_core_cls(name, m_superclass, m_metaclass):
+        assert name.startswith('m_')
+        mirror = bootstrap_classmirror(instsize=0,    # XXX
+                                       m_superclass=m_superclass,
+                                       m_metaclass=m_metaclass,
+                                       name=name[2:])
+        classtable[name] = mirror
+        globals()[name] = mirror
+        return mirror
     
     #    Class Name            Super class name
     cls_nm_tbl = [
-        ["w_Object",           "w_ProtoObject"],
-        ["w_Behavior",         "w_Object"],
-        ["w_ClassDescription", "w_Behavior"],
-        ["w_Class",            "w_ClassDescription"],
-        ["w_Metaclass",        "w_ClassDescription"],
+        ["m_Object",           "m_ProtoObject"],
+        ["m_Behavior",         "m_Object"],
+        ["m_ClassDescription", "m_Behavior"],
+        ["m_Class",            "m_ClassDescription"],
+        ["m_Metaclass",        "m_ClassDescription"],
         ]
-    define_core_cls("w_ProtoObjectClass", W_MetaClass(None, None))
-    define_core_cls("w_ProtoObject", W_Class(w_ProtoObjectClass, None))
+    define_core_cls("m_ProtoObjectClass", None, None)
+    define_core_cls("m_ProtoObject", None, m_ProtoObjectClass)
     for (cls_nm, super_cls_nm) in cls_nm_tbl:
         meta_nm = cls_nm + "Class"
         meta_super_nm = super_cls_nm + "Class"
-        metacls = define_core_cls(
-            meta_nm, W_MetaClass(None, classtable[meta_super_nm], name=meta_nm))
-        define_core_cls(
-            cls_nm, W_Class(metacls, classtable[super_cls_nm], name=cls_nm))
-    w_ProtoObjectClass.w_superclass = w_Class
-    for nm, w_cls_obj in classtable.items():
-        if w_cls_obj.ismetaclass():
-            w_cls_obj.w_class = w_Metaclass
+        m_metacls = define_core_cls(meta_nm, classtable[meta_super_nm], None)
+        define_core_cls(cls_nm, classtable[super_cls_nm], m_metacls)
+    m_ProtoObjectClass.m_superclass = m_Class
+    # at this point, all classes that still lack a m_metaclass are themselves
+    # metaclasses
+    for nm, m_cls_obj in classtable.items():
+        if m_cls_obj.m_metaclass is None:
+            m_cls_obj.m_metaclass = m_Metaclass
 create_classtable()
 
 # ___________________________________________________________________________
 # Other classes
 
-def define_cls(cls_nm, supercls_nm, instvarsize=0, format=POINTERS):
+def define_cls(cls_nm, supercls_nm, instvarsize=0, format=mirror.POINTERS):
     meta_nm = cls_nm + "Class"
     meta_super_nm = supercls_nm + "Class"
-    w_meta_cls = globals()[meta_nm] = classtable[meta_nm] = \
-                 W_MetaClass(w_Metaclass,
-                             classtable[meta_super_nm],
-                             name=meta_nm)
-    w_cls = globals()[cls_nm] = classtable[cls_nm] = \
-            W_Class(w_meta_cls,
-                    classtable[supercls_nm],
-                    name=cls_nm,
-                    instvarsize=instvarsize,
-                    format=format)
-
-define_cls("w_Magnitude", "w_Object")
-define_cls("w_Character", "w_Magnitude", instvarsize=1)
-define_cls("w_Number", "w_Magnitude")
-define_cls("w_Integer", "w_Number")
-define_cls("w_SmallInteger", "w_Integer")
-define_cls("w_Float", "w_Number")
-define_cls("w_Collection", "w_Object")
-define_cls("w_SequencableCollection", "w_Collection")
-define_cls("w_ArrayedCollection", "w_SequencableCollection")
-define_cls("w_String", "w_ArrayedCollection")
-define_cls("w_ByteString", "w_String", format=BYTES)
-define_cls("w_UndefinedObject", "w_Object")
-define_cls("w_Boolean", "w_Object")
-define_cls("w_True", "w_Boolean")
-define_cls("w_False", "w_Boolean")
+    m_meta_cls = globals()[meta_nm] = classtable[meta_nm] = \
+                 bootstrap_classmirror(0,   # XXX
+                                       classtable[meta_super_nm],
+                                       m_Metaclass)
+    m_cls = globals()[cls_nm] = classtable[cls_nm] = \
+                 bootstrap_classmirror(instvarsize,
+                                       classtable[supercls_nm],
+                                       m_meta_cls,
+                                       format=format)
+
+define_cls("m_Magnitude", "m_Object")
+define_cls("m_Character", "m_Magnitude", instvarsize=1)
+define_cls("m_Number", "m_Magnitude")
+define_cls("m_Integer", "m_Number")
+define_cls("m_SmallInteger", "m_Integer")
+define_cls("m_Float", "m_Number", format=mirror.BYTES)
+define_cls("m_Collection", "m_Object")
+define_cls("m_SequencableCollection", "m_Collection")
+define_cls("m_ArrayedCollection", "m_SequencableCollection")
+define_cls("m_String", "m_ArrayedCollection")
+define_cls("m_ByteString", "m_String", format=mirror.BYTES)
+define_cls("m_UndefinedObject", "m_Object")
+define_cls("m_Boolean", "m_Object")
+define_cls("m_True", "m_Boolean")
+define_cls("m_False", "m_Boolean")
+define_cls("m_ByteArray", "m_ArrayedCollection", format=mirror.BYTES)
+define_cls("m_CompiledMethod", "m_ByteArray", format=mirror.COMPILED_METHOD)

Modified: pypy/dist/pypy/lang/smalltalk/fakeimage.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/fakeimage.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/fakeimage.py	Wed Oct 24 22:24:08 2007
@@ -7,14 +7,14 @@
 
 def wrap_int(i):
     if i <= 0x3FFFFFFF and i >= -0x40000000:
-        return model.W_SmallInteger(ct.w_SmallInteger, i)
+        return model.W_SmallInteger(i)
     raise NotImplementedError
 
 def wrap_float(i):
-    return model.W_Float(ct.w_Float,i)
+    return model.W_Float(i)
 
 def wrap_string(str):
-    w_inst = ct.w_ByteString.new(len(str))
+    w_inst = ct.m_ByteString.new(len(str))
     for i in range(len(str)):
         w_inst.setbyte(i, ord(str[i]))
     return w_inst
@@ -23,9 +23,9 @@
     return CharacterTable[ord(c)]
 
 def ord_w_char(w_c):
-    assert w_c.w_class is ct.w_Character
+    assert w_c.getclassmirror() is ct.m_Character
     w_ord = w_c.fetch(CHARACTER_VALUE_INDEX)
-    assert w_ord.w_class is ct.w_SmallInteger
+    assert w_ord.getclassmirror() is ct.m_SmallInteger
     assert isinstance(w_ord, model.W_SmallInteger)
     return w_ord.value
 
@@ -41,15 +41,15 @@
 def wrap_char_table():
     global CharacterTable
     def bld_char(i):
-        w_cinst = ct.w_Character.new()
+        w_cinst = ct.m_Character.new()
         w_cinst.store(CHARACTER_VALUE_INDEX, wrap_int(i))
         return w_cinst
     CharacterTable = [bld_char(i) for i in range(256)]
 wrap_char_table()
 
-w_true  = ct.w_True.new()
-w_false = ct.w_False.new()
-w_nil = ct.w_UndefinedObject.new()
+w_true  = ct.m_True.new()
+w_false = ct.m_False.new()
+w_nil = ct.m_UndefinedObject.new()
 w_mone = wrap_int(-1)
 w_zero = wrap_int(0)
 w_one = wrap_int(1)

Modified: pypy/dist/pypy/lang/smalltalk/interpreter.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/interpreter.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/interpreter.py	Wed Oct 24 22:24:08 2007
@@ -10,9 +10,8 @@
     """Illegal Store."""
 
 
-class W_ContextFrame(model.W_Object):
-    def __init__(self, w_class, method, receiver, arguments, sender = None):
-        model.W_Object.__init__(self, w_class)
+class W_MethodContext(model.W_Object):
+    def __init__(self, method, receiver, arguments, sender = None):
         self.method = method
         self.receiver = receiver
         self.sender = sender
@@ -20,6 +19,13 @@
         self.temps = arguments + [None] * method.tempsize
         self.pc = 0
 
+    def getclassmirror(self):
+        from pypy.lang.smalltalk.classtable import m_MethodContext  # XXX do me
+        return m_MethodContext
+
+    def gethash(self):
+        return 44     # XXX
+
     def pop(self):
         return self.stack.pop()
 
@@ -120,15 +126,15 @@
     def _sendSelfSelector(self, selector, argcount, interp):
         receiver = self.peek(argcount)
         self._sendSelector(selector, argcount, interp,
-                           receiver, receiver.w_class)
+                           receiver, receiver.getclassmirror())
 
     def _sendSuperSelector(self, selector, argcount, interp):
         self._sendSelector(selector, argcount, interp, self.receiver,
-                           self.method.w_compiledin.w_superclass)
+                           self.method.m_compiledin.m_superclass)
 
     def _sendSelector(self, selector, argcount, interp,
-                      receiver, receiverclass):
-        method = receiverclass.lookup(selector)
+                      receiver, m_receiverclass):
+        method = m_receiverclass.lookup(selector)
         assert method
         if method.primitive:
             func = primitives.prim_table[method.primitive]
@@ -422,77 +428,77 @@
         self.object = object
 
 BYTECODE_RANGES = [
-            (  0,  15, W_ContextFrame.pushReceiverVariableBytecode),
-            ( 16,  31, W_ContextFrame.pushTemporaryVariableBytecode),
-            ( 32,  63, W_ContextFrame.pushLiteralConstantBytecode),
-            ( 64,  95, W_ContextFrame.pushLiteralVariableBytecode),
-            ( 96, 103, W_ContextFrame.storeAndPopReceiverVariableBytecode),
-            (104, 111, W_ContextFrame.storeAndPopTemporaryVariableBytecode),
-            (112, W_ContextFrame.pushReceiverBytecode),
-            (113, W_ContextFrame.pushConstantTrueBytecode),
-            (114, W_ContextFrame.pushConstantFalseBytecode),
-            (115, W_ContextFrame.pushConstantNilBytecode),
-            (116, W_ContextFrame.pushConstantMinusOneBytecode),
-            (117, W_ContextFrame.pushConstantZeroBytecode),
-            (118, W_ContextFrame.pushConstantOneBytecode),
-            (119, W_ContextFrame.pushConstantTwoBytecode),
-            (120, W_ContextFrame.returnReceiver),
-            (121, W_ContextFrame.returnTrue),
-            (122, W_ContextFrame.returnFalse),
-            (123, W_ContextFrame.returnNil),
-            (124, W_ContextFrame.returnTopFromMethod),
-            (125, W_ContextFrame.returnTopFromBlock),
-            (126, W_ContextFrame.unknownBytecode),
-            (127, W_ContextFrame.unknownBytecode),
-            (128, W_ContextFrame.extendedPushBytecode),
-            (129, W_ContextFrame.extendedStoreBytecode),
-            (130, W_ContextFrame.extendedStoreAndPopBytecode),
-            (131, W_ContextFrame.singleExtendedSendBytecode),
-            (132, W_ContextFrame.doubleExtendedDoAnythingBytecode),
-            (133, W_ContextFrame.singleExtendedSuperBytecode),
-            (134, W_ContextFrame.secondExtendedSendBytecode),
-            (135, W_ContextFrame.popStackBytecode),
-            (136, W_ContextFrame.duplicateTopBytecode),
-            (137, W_ContextFrame.pushActiveContextBytecode),
-            (138, 143, W_ContextFrame.experimentalBytecode),
-            (144, 151, W_ContextFrame.shortUnconditionalJump),
-            (152, 159, W_ContextFrame.shortConditionalJump),
-            (160, 167, W_ContextFrame.longUnconditionalJump),
-            (168, 171, W_ContextFrame.longJumpIfTrue),
-            (172, 175, W_ContextFrame.longJumpIfFalse),
-            (176, W_ContextFrame.bytecodePrimAdd),
-            (177, W_ContextFrame.bytecodePrimSubtract),
-            (178, W_ContextFrame.bytecodePrimLessThan),
-            (179, W_ContextFrame.bytecodePrimGreaterThan),
-            (180, W_ContextFrame.bytecodePrimLessOrEqual),
-            (181, W_ContextFrame.bytecodePrimGreaterOrEqual),
-            (182, W_ContextFrame.bytecodePrimEqual),
-            (183, W_ContextFrame.bytecodePrimNotEqual),
-            (184, W_ContextFrame.bytecodePrimMultiply),
-            (185, W_ContextFrame.bytecodePrimDivide),
-            (186, W_ContextFrame.bytecodePrimMod),
-            (187, W_ContextFrame.bytecodePrimMakePoint),
-            (188, W_ContextFrame.bytecodePrimBitShift),
-            (189, W_ContextFrame.bytecodePrimDiv),
-            (190, W_ContextFrame.bytecodePrimBitAnd),
-            (191, W_ContextFrame.bytecodePrimBitOr),
-            (192, W_ContextFrame.bytecodePrimAt),
-            (193, W_ContextFrame.bytecodePrimAtPut),
-            (194, W_ContextFrame.bytecodePrimSize),
-            (195, W_ContextFrame.bytecodePrimNext),
-            (196, W_ContextFrame.bytecodePrimNextPut),
-            (197, W_ContextFrame.bytecodePrimAtEnd),
-            (198, W_ContextFrame.bytecodePrimEquivalent),
-            (199, W_ContextFrame.bytecodePrimClass),
-            (200, W_ContextFrame.bytecodePrimBlockCopy),
-            (201, W_ContextFrame.bytecodePrimValue),
-            (202, W_ContextFrame.bytecodePrimValueWithArg),
-            (203, W_ContextFrame.bytecodePrimDo),
-            (204, W_ContextFrame.bytecodePrimNew),
-            (205, W_ContextFrame.bytecodePrimNewWithArg),
-            (206, W_ContextFrame.bytecodePrimPointX),
-            (207, W_ContextFrame.bytecodePrimPointY),
-            (208, 255, W_ContextFrame.sendLiteralSelectorBytecode),
+            (  0,  15, W_MethodContext.pushReceiverVariableBytecode),
+            ( 16,  31, W_MethodContext.pushTemporaryVariableBytecode),
+            ( 32,  63, W_MethodContext.pushLiteralConstantBytecode),
+            ( 64,  95, W_MethodContext.pushLiteralVariableBytecode),
+            ( 96, 103, W_MethodContext.storeAndPopReceiverVariableBytecode),
+            (104, 111, W_MethodContext.storeAndPopTemporaryVariableBytecode),
+            (112, W_MethodContext.pushReceiverBytecode),
+            (113, W_MethodContext.pushConstantTrueBytecode),
+            (114, W_MethodContext.pushConstantFalseBytecode),
+            (115, W_MethodContext.pushConstantNilBytecode),
+            (116, W_MethodContext.pushConstantMinusOneBytecode),
+            (117, W_MethodContext.pushConstantZeroBytecode),
+            (118, W_MethodContext.pushConstantOneBytecode),
+            (119, W_MethodContext.pushConstantTwoBytecode),
+            (120, W_MethodContext.returnReceiver),
+            (121, W_MethodContext.returnTrue),
+            (122, W_MethodContext.returnFalse),
+            (123, W_MethodContext.returnNil),
+            (124, W_MethodContext.returnTopFromMethod),
+            (125, W_MethodContext.returnTopFromBlock),
+            (126, W_MethodContext.unknownBytecode),
+            (127, W_MethodContext.unknownBytecode),
+            (128, W_MethodContext.extendedPushBytecode),
+            (129, W_MethodContext.extendedStoreBytecode),
+            (130, W_MethodContext.extendedStoreAndPopBytecode),
+            (131, W_MethodContext.singleExtendedSendBytecode),
+            (132, W_MethodContext.doubleExtendedDoAnythingBytecode),
+            (133, W_MethodContext.singleExtendedSuperBytecode),
+            (134, W_MethodContext.secondExtendedSendBytecode),
+            (135, W_MethodContext.popStackBytecode),
+            (136, W_MethodContext.duplicateTopBytecode),
+            (137, W_MethodContext.pushActiveContextBytecode),
+            (138, 143, W_MethodContext.experimentalBytecode),
+            (144, 151, W_MethodContext.shortUnconditionalJump),
+            (152, 159, W_MethodContext.shortConditionalJump),
+            (160, 167, W_MethodContext.longUnconditionalJump),
+            (168, 171, W_MethodContext.longJumpIfTrue),
+            (172, 175, W_MethodContext.longJumpIfFalse),
+            (176, W_MethodContext.bytecodePrimAdd),
+            (177, W_MethodContext.bytecodePrimSubtract),
+            (178, W_MethodContext.bytecodePrimLessThan),
+            (179, W_MethodContext.bytecodePrimGreaterThan),
+            (180, W_MethodContext.bytecodePrimLessOrEqual),
+            (181, W_MethodContext.bytecodePrimGreaterOrEqual),
+            (182, W_MethodContext.bytecodePrimEqual),
+            (183, W_MethodContext.bytecodePrimNotEqual),
+            (184, W_MethodContext.bytecodePrimMultiply),
+            (185, W_MethodContext.bytecodePrimDivide),
+            (186, W_MethodContext.bytecodePrimMod),
+            (187, W_MethodContext.bytecodePrimMakePoint),
+            (188, W_MethodContext.bytecodePrimBitShift),
+            (189, W_MethodContext.bytecodePrimDiv),
+            (190, W_MethodContext.bytecodePrimBitAnd),
+            (191, W_MethodContext.bytecodePrimBitOr),
+            (192, W_MethodContext.bytecodePrimAt),
+            (193, W_MethodContext.bytecodePrimAtPut),
+            (194, W_MethodContext.bytecodePrimSize),
+            (195, W_MethodContext.bytecodePrimNext),
+            (196, W_MethodContext.bytecodePrimNextPut),
+            (197, W_MethodContext.bytecodePrimAtEnd),
+            (198, W_MethodContext.bytecodePrimEquivalent),
+            (199, W_MethodContext.bytecodePrimClass),
+            (200, W_MethodContext.bytecodePrimBlockCopy),
+            (201, W_MethodContext.bytecodePrimValue),
+            (202, W_MethodContext.bytecodePrimValueWithArg),
+            (203, W_MethodContext.bytecodePrimDo),
+            (204, W_MethodContext.bytecodePrimNew),
+            (205, W_MethodContext.bytecodePrimNewWithArg),
+            (206, W_MethodContext.bytecodePrimPointX),
+            (207, W_MethodContext.bytecodePrimPointY),
+            (208, 255, W_MethodContext.sendLiteralSelectorBytecode),
             ]
 
 def initialize_bytecode_table():

Added: pypy/dist/pypy/lang/smalltalk/mirror.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/smalltalk/mirror.py	Wed Oct 24 22:24:08 2007
@@ -0,0 +1,150 @@
+import weakref
+from pypy.lang.smalltalk import model, constants
+
+POINTERS = 0
+BYTES = 1
+WORDS = 2
+WEAK_POINTERS = 3
+COMPILED_METHOD = 4
+
+class ClassMirrorError(Exception):
+    pass
+
+def unwrap_int(w_value):
+    if isinstance(w_value, model.W_SmallInteger):
+        return w_value.value
+    raise ClassMirrorError("expected a W_SmallInteger, got %s" % (w_value,))
+
+
+class ClassMirror(object):
+    def __init__(self, w_self):
+        self.w_self = w_self
+        self.invalidate()
+
+    def invalidate(self):
+        self.methoddict = {}
+        self.m_superclass = None
+        self.m_metaclass = None
+        self.name = '?'
+        self.invalid = True
+
+    def check(self):
+        if self.invalid:
+            self.update_mirror()
+
+    def update_mirror(self):
+        "Update the ClassMirror with data from the w_self class."
+        w_self = self.w_self
+        # read and painfully decode the format
+        classformat = unwrap_int(w_self.fetch(constants.CLASS_FORMAT_INDEX))
+        # The classformat in Squeak, as an integer value, is:
+        #    <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec>
+        #                                    <6 bits=instSize\\64><1 bit=0>
+        # In Slang the value is read directly as a boxed integer, so that
+        # the code gets a "pointer" whose bits are set as above, but
+        # shifted one bit to the left and with the lowest bit set to 1.
+
+        # compute the instance size (really the size, not the number of bytes)
+        instsize_lo = (classformat >> 1) & 0x3F
+        instsize_hi = (classformat >> (9 + 1)) & 0xC0
+        self.instance_size = instsize_lo | instsize_hi
+        # decode the instSpec
+        format = (classformat >> 7) & 15
+        self.instance_varsized = format >= 2
+        if format < 4:
+            self.instance_kind = POINTERS
+        elif format == 4:
+            self.instance_kind = WEAK_POINTERS
+        elif format == 6:
+            self.instance_kind = WORDS
+            if self.instance_kind != 0:
+                raise ClassMirrorError("can't have both words and a non-zero "
+                                       "base instance size")
+        elif 8 <= format <= 11:
+            self.instance_kind = BYTES
+            if self.instance_kind != 0:
+                raise ClassMirrorError("can't have both bytes and a non-zero "
+                                       "base instance size")
+        elif 12 <= format <= 15:
+            self.instance_kind = COMPILED_METHOD
+        else:
+            raise ClassMirrorError("unknown format %d" % (format,))
+        self.invalid = False
+
+    def new(self, extrasize=0):
+        self.check()
+        if self.instance_kind == POINTERS:
+            return model.W_PointersObject(self, self.instance_size + extrasize)
+        elif self.instance_kind == WORDS:
+            return model.W_WordsObject(self, extrasize)
+        elif self.instance_kind == BYTES:
+            return model.W_BytesObject(self, extrasize)
+        else:
+            raise NotImplementedError(self.instance_kind)
+
+    # _______________________________________________________________
+    # Methods for querying the format word, taken from the blue book:
+    #
+    # included so that we can reproduce code from the reference impl
+    # more easily
+
+    def ispointers(self):
+        " True if instances of this class have data stored as pointers "
+        XXX   # what about weak pointers?
+        return self.format == POINTERS
+
+    def iswords(self):
+        " True if instances of this class have data stored as numerical words "
+        XXX   # what about weak pointers?
+        return self.format in (POINTERS, WORDS)
+
+    def isbytes(self):
+        " True if instances of this class have data stored as numerical bytes "
+        return self.format == BYTES
+
+    def isvariable(self):
+        " True if instances of this class have indexed inst variables "
+        return self.instance_varsized
+
+    def instsize(self):
+        " Number of named instance variables for each instance of this class "
+        return self.instance_size
+
+    # _______________________________________________________________
+    # Methods for querying the format word, taken from the blue book:
+
+    def __repr__(self):
+        return "<ClassMirror %s>" % (self.name,)
+
+    def lookup(self, selector):
+        if selector in self.methoddict:
+            return self.methoddict[selector]
+        elif self.m_superclass != None:
+            return self.m_superclass.lookup(selector)
+        else:
+            return None
+
+    def installmethod(self, selector, method):
+        "NOT_RPYTHON"     # this is only for testing.
+        assert isinstance(method, model.W_CompiledMethod)
+        self.methoddict[selector] = method
+        method.m_compiledin = self
+
+
+class MirrorCache:
+    def __init__(self):
+        self.cache = weakref.WeakKeyDictionary()
+
+    def get_or_build(self, w_class):
+        try:
+            mirror = self.cache[w_class]
+        except KeyError:
+            mirror = self.cache[w_class] = ClassMirror(w_class)
+        return mirror
+
+    def getmirror(self, w_class):
+        mirror = self.get_or_build(w_class)
+        mirror.check()
+        return mirror
+
+mirrorcache = MirrorCache()

Modified: pypy/dist/pypy/lang/smalltalk/model.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/model.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/model.py	Wed Oct 24 22:24:08 2007
@@ -1,48 +1,69 @@
 
 class W_Object(object):
-    def __init__(self, w_class):
-        self.w_class = w_class
-        self.w_hash = None # XXX initial value?
 
     def size(self):
         return 0
 
-    def instvarsize(self):
-        return self.w_class.instvarsize    
-        
+    def getclassmirror(self):
+        raise NotImplementedError
+
+    def gethash(self):
+        raise NotImplementedError
+
     def invariant(self):
-        return (hasattr(self, 'w_class') and
-                self.w_class != None)
-                
-    def as_w_class_instvarsize(self):
-        return self.vars[3] # hardcoded position of instvar                 
+        return True
 
 class W_SmallInteger(W_Object):
-    def __init__(self, w_class, value):
-        W_Object.__init__(self, w_class)
+    def __init__(self, value):
         self.value = value
-        
+
+    def getclassmirror(self):
+        from pypy.lang.smalltalk.classtable import m_SmallInteger
+        return m_SmallInteger
+
+    def gethash(self):
+        return self.value    # XXX check this
+
     def invariant(self):
-        W_Object.invariant(self)
-        assert hasattr(self, 'value')
-        assert self.value != None
+        return isinstance(self.value, int)
 
 class W_Float(W_Object):
-    def __init__(self, w_class, value):
-        W_Object.__init__(self, w_class)
+    def __init__(self, value):
         self.value = value
-        
+
+    def getclassmirror(self):
+        from pypy.lang.smalltalk.classtable import m_Float
+        return m_Float
+
+    def gethash(self):
+        return XXX    # check this
+
     def invariant(self):
-        return (W_Object.invariant(self) and
-                hasattr(self, 'value') and
-                self.value != None)
-        
+        return self.value is not None        # XXX but later:
+        #return isinstance(self.value, float)
+
+class W_ObjectWithStoredClass(W_Object):
+    """ The base class of objects that store 'm_class' explicitly. """
+    def __init__(self, m_class):
+        self.m_class = m_class
+        self.hash = 42             # XXX
+
+    def getclassmirror(self):
+        return self.m_class
 
-class W_PointersObject(W_Object):
+    def gethash(self):
+        return self.hash
+
+    def invariant(self):
+        from pypy.lang.smalltalk.mirror import ClassMirror
+        return (isinstance(self.m_class, ClassMirror) and
+                1)#isinstance(self.hash, int)) XXX
+
+class W_PointersObject(W_ObjectWithStoredClass):
     """ The normal object """
-    def __init__(self, w_class, size=0):
-        W_Object.__init__(self, w_class)
-        self.vars = [None] * (w_class.instvarsize + size)
+    def __init__(self, m_class, size):
+        W_ObjectWithStoredClass.__init__(self, m_class)
+        self.vars = [None] * size
 
     def fetch(self, index):
         return self.vars[index]
@@ -54,14 +75,12 @@
         return len(self.vars)
 
     def invariant(self):
-        return (W_Object.invariant(self) and
-                hasattr(self, 'vars') and
-                self.vars != None)
-        
+        return (W_ObjectWithStoredClass.invariant(self) and
+                isinstance(self.vars, list))
 
-class W_BytesObject(W_Object):
-    def __init__(self, w_class, size):
-        W_Object.__init__(self, w_class)
+class W_BytesObject(W_ObjectWithStoredClass):
+    def __init__(self, m_class, size):
+        W_ObjectWithStoredClass.__init__(self, m_class)
         self.bytes = ['\x00'] * size
         
     def getbyte(self, n):
@@ -74,14 +93,16 @@
         return len(self.bytes)    
 
     def invariant(self):
-        return (W_Object.invariant(self) and
-                hasattr(self, 'bytes') and
-                self.bytes != None)
-
+        if not W_ObjectWithStoredClass.invariant(self):
+            return False
+        for c in self.bytes:
+            if not isinstance(c, str) or len(c) != 1:
+                return False
+        return True
 
-class W_WordsObject(W_Object):
-    def __init__(self, w_class, size):
-        W_Object.__init__(self, w_class)
+class W_WordsObject(W_ObjectWithStoredClass):
+    def __init__(self, m_class, size):
+        W_ObjectWithStoredClass.__init__(self, m_class)
         self.words = [0] * size
         
     def getword(self, n):
@@ -94,9 +115,8 @@
         return len(self.words)   
 
     def invariant(self):
-        return (W_Object.invariant(self) and
-                hasattr(self, 'words') and
-                self.words != None)
+        return (W_ObjectWithStoredClass.invariant(self) and
+                isinstance(self.words, list))
 
 class W_CompiledMethod(W_Object):
     """My instances are methods suitable for interpretation by the virtual machine.  This is the only class in the system whose instances intermix both indexable pointer fields and indexable integer fields.
@@ -120,112 +140,36 @@
 
     The trailer has two variant formats.  In the first variant, the last byte is at least 252 and the last four bytes represent a source pointer into one of the sources files (see #sourcePointer).  In the second variant, the last byte is less than 252, and the last several bytes are a compressed version of the names of the method's temporary variables.  The number of bytes used for this purpose is the value of the last byte in the method.
     """
-    def __init__(self, w_class, size, bytes="", argsize=0, 
-                 tempsize=0, primitive=0, w_compiledin=None):
-        W_Object.__init__(self, w_class)
+    def __init__(self, size, bytes, argsize=0, 
+                 tempsize=0, primitive=0, m_compiledin=None):
         self.literals = [None] * size
-        self.w_compiledin = w_compiledin
+        self.m_compiledin = m_compiledin
         self.bytes = bytes
         self.argsize = argsize
         self.tempsize = tempsize
         self.primitive = primitive
 
+    def getclassmirror(self):
+        from pypy.lang.smalltalk.classtable import m_CompiledMethod
+        return m_CompiledMethod
+
+    def gethash(self):
+        return 43     # XXX
+
     def createFrame(self, receiver, arguments, sender = None):
-        from pypy.lang.smalltalk.interpreter import W_ContextFrame
+        from pypy.lang.smalltalk.interpreter import W_MethodContext
         assert len(arguments) == self.argsize
-        return W_ContextFrame(None, self, receiver, arguments, sender)
+        return W_MethodContext(self, receiver, arguments, sender)
 
     def invariant(self):
         return (W_Object.invariant(self) and
                 hasattr(self, 'literals') and
-                self.literals != None and 
+                self.literals is not None and 
                 hasattr(self, 'bytes') and
-                self.bytes != None and 
+                self.bytes is not None and 
                 hasattr(self, 'argsize') and
-                self.argsize != None and 
+                self.argsize is not None and 
                 hasattr(self, 'tempsize') and
-                self.tempsize != None and 
+                self.tempsize is not None and 
                 hasattr(self, 'primitive') and
-                self.primitive != None)       
-
-# ____________________________________________________________ 
-
-POINTERS = 0
-VAR_POINTERS = 1
-BYTES = 2
-WORDS = 3
-WEAK_POINTERS = 4
-
-class W_Class(W_Object):
-    def __init__(self, w_class, w_superclass, instvarsize=0,
-                 format=POINTERS, name="?"):
-        W_Object.__init__(self, w_class)
-        self.name = name
-        self.w_superclass = w_superclass
-        self.methoddict = {}
-        self.instvarsize = instvarsize
-        self.format = format
-
-    # _______________________________________________________________
-    # Methods for querying the format word, taken from the blue book:
-    #
-    # included so that we can reproduce code from the reference impl
-    # more easily
-
-    def ispointers(self):
-        " True if instances of this class have data stored as pointers "
-        return self.format in (POINTERS, VAR_POINTERS)
-
-    def iswords(self):
-        " True if instances of this class have data stored as numerical words "
-        return self.format in (POINTERS, VAR_POINTERS, WORDS)
-
-    def isbytes(self):
-        " True if instances of this class have data stored as numerical bytes "
-        return self.format == BYTES
-
-    def isvariable(self):
-        " True if instances of this class have indexed inst variables "
-        return self.format in (VAR_POINTERS, WORDS, BYTES)
-
-    def instsize(self):
-        " Number of named instance variables for each instance of this class "
-        return self.instvarsize
-
-    def ismetaclass(self):
-        return False
-
-    # _______________________________________________________________
-    # Methods for querying the format word, taken from the blue book:
-
-    def new(self, size=0):
-        if self.format == POINTERS:
-            assert size == 0
-            return W_PointersObject(self)
-        elif self.format == VAR_POINTERS:
-            return W_PointersObject(w_class=self, size=size)
-        elif self.format == WORDS:
-            return W_WordsObject(w_class=self, size=size)
-        elif self.format == BYTES:
-            return W_BytesObject(w_class=self, size=size)
-        else:
-            raise NotImplementedError(self.format)
-
-    def __repr__(self):
-        return "W_Class(%s)" % self.name
-
-    def lookup(self, selector):
-        if selector in self.methoddict:
-            return self.methoddict[selector]
-        elif self.w_superclass != None:
-            return self.w_superclass.lookup(selector)
-        else:
-            return None
-
-    def installmethod(self, selector, method):
-        self.methoddict[selector] = method
-        method.w_compiledin = self
-
-class W_MetaClass(W_Class):
-    def ismetaclass(self):
-        return True
+                self.primitive is not None)       

Modified: pypy/dist/pypy/lang/smalltalk/primitives.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/primitives.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/primitives.py	Wed Oct 24 22:24:08 2007
@@ -1,5 +1,5 @@
 import operator
-import pypy.lang.smalltalk.model as model
+from pypy.lang.smalltalk import model, mirror
 import pypy.lang.smalltalk.classtable as ct
 import pypy.lang.smalltalk.fakeimage as fimg
 from pypy.rlib import rarithmetic
@@ -205,12 +205,14 @@
 def common_at(stack):
     [w_obj, w_idx] = stack
     idx = unwrap_int(w_idx)
+    # XXX should be idx-1, probably
     assert_valid_index(idx, w_obj)
     return w_obj, idx
 
 def common_at_put(stack):
     [w_obj, w_idx, w_val] = stack
     idx = unwrap_int(w_idx)
+    # XXX should be idx-1, probably
     assert_valid_index(idx, w_obj)
     return w_obj, idx, w_val
 
@@ -231,7 +233,7 @@
 @stack(1)
 def func(stack):
     [w_obj] = stack
-    if not w_obj.w_class.isvariable():
+    if not w_obj.getclassmirror().isvariable():
         raise PrimitiveFailedError()
     return w_obj.size()
 
@@ -246,7 +248,7 @@
 @stack(3)
 def func(stack):
     w_obj, idx, w_val = common_at_put(stack)
-    if w_val.w_class is not ct.w_Character:
+    if w_val.getclassmirror() is not ct.m_Character:
         raise PrimitiveFailedError()
     w_obj.setbyte(idx, fimg.ord_w_char(w_val))
     return w_val
@@ -271,7 +273,8 @@
 def func(stack):
     [w_rcvr, w_idx] = stack
     idx = unwrap_int(w_idx)
-    assert_bounds(idx, 0, w_rcvr.w_class.instvarsize)
+    # XXX should be idx-1, probably
+    assert_bounds(idx, 0, w_rcvr.getclassmirror().instance_size)
     return w_rcvr.fetch(idx)
 
 @primitive(OBJECT_AT_PUT)
@@ -279,7 +282,8 @@
 def func(stack):
     [w_rcvr, w_idx, w_val] = stack
     idx = unwrap_int(w_idx)
-    assert_bounds(idx, 0, w_rcvr.w_class.instvarsize)
+    # XXX should be idx-1, probably
+    assert_bounds(idx, 0, w_rcvr.getclassmirror().instance_size)
     w_rcvr.store(idx, w_val)
     return w_val
 
@@ -287,18 +291,20 @@
 @stack(1)
 def func(stack):
     [w_cls] = stack
-    if not isinstance(w_cls, model.W_Class) or w_cls.isvariable():
+    m_cls = mirror.mirrorcache.getmirror(w_cls)
+    if m_cls.isvariable():
         raise PrimitiveFailedError()
-    return w_cls.new()
+    return m_cls.new()
 
 @primitive(NEW_WITH_ARG)
 @stack(2)
 def func(stack):
     [w_cls, w_size] = stack
-    if not isinstance(w_cls, model.W_Class) or not w_cls.isvariable():
+    m_cls = mirror.mirrorcache.getmirror(w_cls)
+    if not m_cls.isvariable():
         raise PrimitiveFailedError()
     size = unwrap_int(w_size)
-    return w_cls.new(size)
+    return m_cls.new(size)
 
 @primitive(ARRAY_BECOME_ONE_WAY)
 def func(frame):
@@ -311,12 +317,12 @@
     # Might be restricted to fixed length fields?
     [w_rcvr, w_idx] = stack
     idx = unwrap_int(w_idx)
-    w_cls = w_rcvr.w_class
+    m_cls = w_rcvr.getclassmirror()
     if idx < 0:
         raise PrimitiveFailedError()
-    if idx < w_cls.instvarsize:
+    if idx < m_cls.instsize():
         return w_rcvr.fetch(idx)
-    idx -= w_cls.instvarsize
+    idx -= m_cls.instsize()
     if idx < w_rcvr.size():
         return subscript(idx, w_rcvr)
     raise PrimitiveFailedError()

Modified: pypy/dist/pypy/lang/smalltalk/squeakimage.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/squeakimage.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/squeakimage.py	Wed Oct 24 22:24:08 2007
@@ -1,6 +1,7 @@
 import py
 from pypy.lang.smalltalk import model 
 from pypy.lang.smalltalk import fakeimage 
+from pypy.lang.smalltalk.mirror import mirrorcache
 from pypy.rlib import objectmodel
 
 def int2str(integer):
@@ -298,11 +299,11 @@
     def fillin_pointersobject(self, w_pointersobject):
         assert self.pointers is not None
         w_pointersobject.vars = [g_object.w_object for g_object in self.pointers]
-        w_pointersobject.w_class = self.g_class.w_object
+        w_pointersobject.m_class = mirrorcache.get_or_build(self.g_class.w_object)
         
     def fillin_wordsobject(self, w_wordsobject):
         w_wordsobject.words = self.chunk.data
-        w_wordsobject.w_class = self.g_class.w_object
+        w_wordsobject.m_class = mirrorcache.get_or_build(self.g_class.w_object)
 
     def fillin_bytesobject(self, w_bytesobject):
         bytes = []
@@ -311,7 +312,7 @@
             bytes.append(chr((each >> 16) & 0xff)) 
             bytes.append(chr((each >> 8) & 0xff)) 
             bytes.append(chr((each >> 0) & 0xff))
-        w_bytesobject.w_class = self.g_class.w_object
+        w_bytesobject.m_class = mirrorcache.get_or_build(self.g_class.w_object)
         w_bytesobject.bytes = bytes[:-(self.format & 3)] # omit odd bytes
  
     def fillin_compiledmethod(self, w_compiledmethod):
@@ -336,8 +337,9 @@
             l.append(int2str(each))
         bytes = "".join(l)
         bytes = bytes[:-(self.format & 3)] 
+        # XXX assert mirrorcache.get_or_build(self.g_class.w_object) is
+        #            ct.m_CompiledMethod
         w_compiledmethod.__init__(
-            w_class = self.g_class.w_object,
             size = literalsize,
             bytes = bytes,
             argsize = numargs,

Modified: pypy/dist/pypy/lang/smalltalk/test/test_classtable.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_classtable.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_classtable.py	Wed Oct 24 22:24:08 2007
@@ -1,30 +1,22 @@
 from pypy.lang.smalltalk.classtable import classtable
 import pypy.lang.smalltalk.classtable as ct
 
-def inherits_from(w_cls, w_superclass):
-    w_p = w_cls
-    while w_p and w_p != w_superclass:
-        w_p = w_p.w_superclass
-    return w_p == w_superclass
+def inherits_from(m_cls, m_superclass):
+    m_p = m_cls
+    while m_p and m_p != m_superclass:
+        m_p = m_p.m_superclass
+    return m_p == m_superclass
 
 def test_every_class_is_an_instance_of_a_metaclass():
-    for (nm, w_cls) in classtable.items():
-        assert w_cls.ismetaclass() or w_cls.w_class.ismetaclass() # ?
+    for (nm, m_cls) in classtable.items():
+        assert (m_cls.m_metaclass is ct.m_Metaclass or
+                m_cls.m_metaclass.m_metaclass is ct.m_Metaclass)
         
 def test_every_metaclass_inherits_from_class_and_behavior():
-    for (nm, w_cls) in classtable.items():
-        if w_cls.ismetaclass():
-            assert inherits_from(w_cls, ct.w_Class)
-    assert inherits_from(ct.w_Class, ct.w_Behavior)
-
-def test_every_metaclass_is_an_instance_of_metaclass():
-    for (nm, w_cls) in classtable.items():
-        if w_cls.ismetaclass():
-            assert w_cls.w_class is ct.w_Metaclass
+    for (nm, m_cls) in classtable.items():
+        if m_cls.m_metaclass is ct.m_Metaclass:
+            assert inherits_from(m_cls, ct.m_Class)
+    assert inherits_from(ct.m_Class, ct.m_Behavior)
 
 def test_metaclass_of_metaclass_is_an_instance_of_metaclass():
-    assert ct.w_Metaclass.w_class.w_class is ct.w_Metaclass
-    
-        
-
-
+    assert ct.m_Metaclass.m_metaclass.m_metaclass is ct.m_Metaclass

Modified: pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_interpreter.py	Wed Oct 24 22:24:08 2007
@@ -1,7 +1,10 @@
 import py
-from pypy.lang.smalltalk import model, interpreter, primitives
+from pypy.lang.smalltalk import model, interpreter, primitives, mirror
+from pypy.lang.smalltalk.fakeimage import wrap_int
 import pypy.lang.smalltalk.classtable as ct
 
+mockclassmirror = ct.bootstrap_classmirror
+
 # expose the bytecode's values as global constants.
 # Bytecodes that have a whole range are exposed as global functions:
 # call them with an argument 'n' to get the bytecode number 'base + n'.
@@ -24,7 +27,7 @@
 
 def new_interpreter(bytes, receiver="receiver"):
     assert isinstance(bytes, str)
-    w_method = model.W_CompiledMethod(None, 0, bytes=bytes,
+    w_method = model.W_CompiledMethod(0, bytes=bytes,
                                       argsize=2, tempsize=1)
     w_frame = w_method.createFrame(receiver, ["foo", "bar"])
     interp = interpreter.Interpreter()
@@ -32,7 +35,7 @@
     return interp
 
 def test_create_frame():
-    w_method = model.W_CompiledMethod(None, 0, bytes="hello",
+    w_method = model.W_CompiledMethod(0, bytes="hello",
                                       argsize=2, tempsize=1)
     w_frame = w_method.createFrame("receiver", ["foo", "bar"])
     assert w_frame.receiver == "receiver"
@@ -73,8 +76,7 @@
 def test_pushReceiverVariableBytecode(bytecode = (pushReceiverVariableBytecode(0) +
                                                   pushReceiverVariableBytecode(1) +
                                                   pushReceiverVariableBytecode(2))):
-    w_democlass = model.W_Class(None, None, 3)
-    w_demo = w_democlass.new()
+    w_demo = mockclassmirror(3).new()
     w_demo.store(0, "egg")
     w_demo.store(1, "bar")
     w_demo.store(2, "baz")
@@ -105,8 +107,7 @@
     assert interp.activeContext.stack == ["a", "b", "c"]
 
 def test_pushLiteralVariableBytecode(bytecode=pushLiteralVariableBytecode(0)):
-    w_associationclass = model.W_Class(None, None, 2)
-    w_association = w_associationclass.new()
+    w_association = mockclassmirror(2).new()
     w_association.store(0, "mykey")
     w_association.store(1, "myvalue")
     interp = new_interpreter(bytecode)
@@ -116,9 +117,9 @@
 
 def test_storeAndPopReceiverVariableBytecode(bytecode=storeAndPopReceiverVariableBytecode,
                                              popped=True):
-    w_class = model.W_Class(None, None, 8)
+    m_class = mockclassmirror(8)
     for index in range(8):
-        w_object = w_class.new()
+        w_object = m_class.new()
         interp = new_interpreter(pushConstantTrueBytecode + bytecode(index))
         interp.activeContext.receiver = w_object
         interp.step()
@@ -194,18 +195,18 @@
     interp.step()
     assert interp.activeContext.stack == [interp.ZERO, interp.ZERO]
 
-# w_class - the class from which the method is going to be called
+# m_class - the class from which the method is going to be called
 # (and on which it is going to be installed)
 # w_object - the actual object we will be sending the method to
 # bytecodes - the bytecode to be executed
-def sendBytecodesTest(w_class, w_object, bytecodes):
+def sendBytecodesTest(m_class, w_object, bytecodes):
     for bytecode, result in [ (returnReceiver, w_object), 
           (returnTrue, interpreter.Interpreter.TRUE), 
           (returnFalse, interpreter.Interpreter.FALSE),
           (returnNil, interpreter.Interpreter.NIL),
           (returnTopFromMethod, interpreter.Interpreter.ONE) ]:
-        w_class.installmethod("foo",
-                              model.W_CompiledMethod(None, 0, pushConstantOneBytecode + bytecode))
+        m_class.installmethod("foo",
+                              model.W_CompiledMethod(0, pushConstantOneBytecode + bytecode))
         interp = new_interpreter(bytecodes)
         interp.activeContext.method.literals = ["foo"]
         interp.activeContext.push(w_object)
@@ -214,7 +215,7 @@
         assert interp.activeContext.sender == callerContext
         assert interp.activeContext.stack == []
         assert interp.activeContext.receiver == w_object
-        assert interp.activeContext.method == w_class.methoddict["foo"]
+        assert interp.activeContext.method == m_class.methoddict["foo"]
         assert callerContext.stack == []
         interp.step()
         interp.step()
@@ -222,42 +223,42 @@
         assert interp.activeContext.stack == [result]
 
 def test_sendLiteralSelectorBytecode():
-    w_class = model.W_Class(None, None)
-    w_object = w_class.new()
-    sendBytecodesTest(w_class, w_object, sendLiteralSelectorBytecode(0))
+    m_class = mockclassmirror(0)
+    w_object = m_class.new()
+    sendBytecodesTest(m_class, w_object, sendLiteralSelectorBytecode(0))
         
 def test_fibWithArgument():
     bytecode = ''.join(map(chr, [ 16, 119, 178, 154, 118, 164, 11, 112, 16, 118, 177, 224, 112, 16, 119, 177, 224, 176, 124 ]))
-    w_class = model.W_Class(None, None)
-    w_class.installmethod("fib:", model.W_CompiledMethod(None, 1, bytecode, 1))
-    w_class.methoddict["fib:"].literals[0] = "fib:"
-    w_object = w_class.new()
+    m_class = mockclassmirror(0)
+    method = model.W_CompiledMethod(1, bytecode, 1)
+    method.literals[0] = "fib:"
+    m_class.installmethod("fib:", method)
+    w_object = m_class.new()
     interp = new_interpreter(sendLiteralSelectorBytecode(16) + returnTopFromMethod)
     interp.activeContext.method.literals = ["fib:"]
     interp.activeContext.push(w_object)
-    interp.activeContext.push(model.W_SmallInteger(None, 8))
+    interp.activeContext.push(wrap_int(8))
     result = interp.interpret()
     assert primitives.unwrap_int(result) == 34
 
 def test_send_to_primitive():
-    w_smallintclass = model.W_Class(None, None)
-    prim_meth = model.W_CompiledMethod(None, 0, "", argsize=1,
+    m_smallintclass = ct.m_SmallInteger
+    prim_meth = model.W_CompiledMethod(0, "", argsize=1,
                                        primitive=primitives.SUBTRACT)
-    w_smallintclass.installmethod("sub", prim_meth)
-    w_50 = model.W_SmallInteger(w_smallintclass, 50)
-    w_50.w_class = w_smallintclass
-    w_8 = model.W_SmallInteger(w_smallintclass, 8)
-    w_8.w_class = w_smallintclass
-    interp = new_interpreter(sendLiteralSelectorBytecode(1 + 16))
-    interp.activeContext.method.literals = ["foo", "sub"]
-    interp.activeContext.push(w_50)
-    interp.activeContext.push(w_8)
-    callerContext = interp.activeContext
-    interp.step()
-    assert interp.activeContext is callerContext
-    assert len(interp.activeContext.stack) == 1
-    w_result = interp.activeContext.pop()
-    assert primitives.unwrap_int(w_result) == 42
+    m_smallintclass.installmethod("sub", prim_meth)
+    try:
+        interp = new_interpreter(sendLiteralSelectorBytecode(1 + 16))
+        interp.activeContext.method.literals = ["foo", "sub"]
+        interp.activeContext.push(wrap_int(50))
+        interp.activeContext.push(wrap_int(8))
+        callerContext = interp.activeContext
+        interp.step()
+        assert interp.activeContext is callerContext
+        assert len(interp.activeContext.stack) == 1
+        w_result = interp.activeContext.pop()
+        assert primitives.unwrap_int(w_result) == 42
+    finally:
+        del m_smallintclass.methoddict['sub']    # clean up after you
 
 def test_longJumpIfTrue():
     interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15))
@@ -330,8 +331,7 @@
     test_pushLiteralVariableBytecode(extendedPushBytecode + chr((3<<6) + 0))
 
 def storeAssociation(bytecode):
-    w_associationclass = model.W_Class(None, None, 2)
-    w_association = w_associationclass.new()
+    w_association = mockclassmirror(2).new()
     w_association.store(0, "mykey")
     w_association.store(1, "myvalue")
     interp = new_interpreter(pushConstantOneBytecode + bytecode)
@@ -353,13 +353,13 @@
 
 def test_callPrimitiveAndPush_fallback():
     interp = new_interpreter(bytecodePrimAdd)
-    w_class = model.W_Class(None, None)
-    w_class.installmethod("+", model.W_CompiledMethod(None, 1, "", 1))
-    w_object = w_class.new()
+    m_class = mockclassmirror(0)
+    m_class.installmethod("+", model.W_CompiledMethod(1, "", 1))
+    w_object = m_class.new()
     interp.activeContext.push(w_object)
     interp.activeContext.push(interp.ONE)
     interp.step()
-    assert interp.activeContext.method == w_class.methoddict["+"]
+    assert interp.activeContext.method == m_class.methoddict["+"]
     assert interp.activeContext.receiver is w_object
     assert interp.activeContext.gettemp(0) == interp.ONE
     assert interp.activeContext.stack == []
@@ -380,49 +380,49 @@
                                           interp.FALSE, interp.TRUE]
 
 def test_singleExtendedSendBytecode():
-    w_class = model.W_Class(None, None)
-    w_object = w_class.new()
-    sendBytecodesTest(w_class, w_object, singleExtendedSendBytecode + chr((0<<5)+0))
+    m_class = mockclassmirror(0)
+    w_object = m_class.new()
+    sendBytecodesTest(m_class, w_object, singleExtendedSendBytecode + chr((0<<5)+0))
 
 def test_singleExtendedSuperBytecode(bytecode=singleExtendedSuperBytecode + chr((0<<5) + 0)):
-    w_supersuper = model.W_Class(None, None)
-    w_super = model.W_Class(None, w_supersuper)
-    w_class = model.W_Class(None, w_super)
-    w_object = w_class.new()
-    # first call method installed in w_class
+    m_supersuper = mockclassmirror(0)
+    m_super = mockclassmirror(0, m_superclass=m_supersuper)
+    m_class = mockclassmirror(0, m_superclass=m_super)
+    w_object = m_class.new()
+    # first call method installed in m_class
     bytecodes = singleExtendedSendBytecode + chr(0)
     # which does a call to its super
-    w_class.installmethod("foo",
-                          model.W_CompiledMethod(None, 0, bytecode))
+    m_class.installmethod("foo",
+                          model.W_CompiledMethod(0, bytecode))
     # and that one again to its super
-    w_super.installmethod("foo",
-                          model.W_CompiledMethod(None, 0, bytecode))
-    w_supersuper.installmethod("foo",
-                               model.W_CompiledMethod(None, 0, ""))
-    w_class.methoddict["foo"].literals = ["foo"]
-    w_super.methoddict["foo"].literals = ["foo"]
+    m_super.installmethod("foo",
+                          model.W_CompiledMethod(0, bytecode))
+    m_supersuper.installmethod("foo",
+                               model.W_CompiledMethod(0, ""))
+    m_class.methoddict["foo"].literals = ["foo"]
+    m_super.methoddict["foo"].literals = ["foo"]
     interp = new_interpreter(bytecodes)
     interp.activeContext.method.literals = ["foo"]
     interp.activeContext.push(w_object)
-    for w_specificclass in [w_class, w_super, w_supersuper]:
+    for m_specificclass in [m_class, m_super, m_supersuper]:
         callerContext = interp.activeContext
         interp.step()
         assert interp.activeContext.sender == callerContext
         assert interp.activeContext.stack == []
         assert interp.activeContext.receiver == w_object
-        assert interp.activeContext.method == w_specificclass.methoddict["foo"]
+        assert interp.activeContext.method == m_specificclass.methoddict["foo"]
         assert callerContext.stack == []
 
 def test_secondExtendedSendBytecode():
-    w_class = model.W_Class(None, None)
-    w_object = w_class.new()
-    sendBytecodesTest(w_class, w_object, secondExtendedSendBytecode + chr(0)) 
+    m_class = mockclassmirror(0)
+    w_object = m_class.new()
+    sendBytecodesTest(m_class, w_object, secondExtendedSendBytecode + chr(0)) 
 
 def test_doubleExtendedDoAnythinBytecode():
-    w_class = model.W_Class(None, None)
-    w_object = w_class.new()
+    m_class = mockclassmirror(0)
+    w_object = m_class.new()
 
-    sendBytecodesTest(w_class, w_object, doubleExtendedDoAnythingBytecode + chr((0<<5) + 0) + chr(0))
+    sendBytecodesTest(m_class, w_object, doubleExtendedDoAnythingBytecode + chr((0<<5) + 0) + chr(0))
 
     test_singleExtendedSuperBytecode(doubleExtendedDoAnythingBytecode + (chr((1<<5) + 0) + chr(0)))
 

Modified: pypy/dist/pypy/lang/smalltalk/test/test_model.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_model.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_model.py	Wed Oct 24 22:24:08 2007
@@ -1,28 +1,31 @@
 import py
-from pypy.lang.smalltalk import model
+from pypy.lang.smalltalk import model, mirror
+import pypy.lang.smalltalk.classtable as ct
+
+mockclassmirror = ct.bootstrap_classmirror
 
 def test_new():
-    w_mycls = model.W_Class(None, None)
-    w_myinstance = w_mycls.new()
-    assert isinstance(w_myinstance, model.W_Object)
-    assert w_myinstance.w_class is w_mycls
+    m_mycls = mockclassmirror(0)
+    w_myinstance = m_mycls.new()
+    assert isinstance(w_myinstance, model.W_PointersObject)
+    assert w_myinstance.getclassmirror() is m_mycls
 
 def test_new_namedvars():
-    w_mycls = model.W_Class(None, None, 3)
-    w_myinstance = w_mycls.new()
+    m_mycls = mockclassmirror(3)
+    w_myinstance = m_mycls.new()
     assert isinstance(w_myinstance, model.W_PointersObject)
-    assert w_myinstance.w_class is w_mycls
+    assert w_myinstance.getclassmirror() is m_mycls
     assert w_myinstance.fetch(0) is None
     py.test.raises(IndexError, lambda: w_myinstance.fetch(3))
     w_myinstance.store(1, w_myinstance)
     assert w_myinstance.fetch(1) is w_myinstance
 
 def test_bytes_object():
-    w_class = model.W_Class(None, None, format=model.BYTES)
-    w_bytes = w_class.new(20)
-    assert w_bytes.w_class is w_class
+    m_class = mockclassmirror(0, format=mirror.BYTES)
+    w_bytes = m_class.new(20)
+    assert w_bytes.getclassmirror() is m_class
     assert w_bytes.size() == 20
-    assert w_bytes.instvarsize() == 0
+    assert m_class.instsize() == 0
     assert w_bytes.getbyte(3) == 00
     w_bytes.setbyte(3, 0xAA)  
     assert w_bytes.getbyte(3) == 0xAA
@@ -30,11 +33,11 @@
     py.test.raises(IndexError, lambda: w_bytes.getbyte(20))
 
 def test_word_object():
-    w_class = model.W_Class(None, None, format=model.WORDS)
-    w_bytes = w_class.new(20)
-    assert w_bytes.w_class is w_class
+    m_class = mockclassmirror(0, format=mirror.WORDS)
+    w_bytes = m_class.new(20)
+    assert w_bytes.getclassmirror() is m_class
     assert w_bytes.size() == 20
-    assert w_bytes.instvarsize() == 0
+    assert m_class.instsize() == 0
     assert w_bytes.getword(3) == 0
     w_bytes.setword(3, 42)  
     assert w_bytes.getword(3) == 42
@@ -42,21 +45,20 @@
     py.test.raises(IndexError, lambda: w_bytes.getword(20))
 
 def test_method_lookup():
-	w_class = model.W_Class(None, None)
-	w_class.methoddict["foo"] = 1
-	w_class.methoddict["bar"] = 2
-	w_subclass = model.W_Class(None, w_class)
-	w_subclass.methoddict["foo"] = 3
-	assert w_class.lookup("foo") == 1
-	assert w_class.lookup("bar") == 2
-	assert w_class.lookup("zork") == None
-	assert w_subclass.lookup("foo") == 3
-	assert w_subclass.lookup("bar") == 2
-	assert w_subclass.lookup("zork") == None
-
-def test_w_compiledin():
-        w_super = model.W_Class(None,None)
-        w_class = model.W_Class(None,w_super)
-        w_super.installmethod("foo",
-                              model.W_CompiledMethod(None, 0))
-        assert w_class.lookup("foo").w_compiledin == w_super
+    m_class = mockclassmirror(0)
+    m_class.methoddict["foo"] = 1
+    m_class.methoddict["bar"] = 2
+    m_subclass = mockclassmirror(0, m_superclass=m_class)
+    m_subclass.methoddict["foo"] = 3
+    assert m_class.lookup("foo") == 1
+    assert m_class.lookup("bar") == 2
+    assert m_class.lookup("zork") == None
+    assert m_subclass.lookup("foo") == 3
+    assert m_subclass.lookup("bar") == 2
+    assert m_subclass.lookup("zork") == None
+
+def test_m_compiledin():
+    m_super = mockclassmirror(0)
+    m_class = mockclassmirror(0, m_superclass=m_super)
+    m_super.installmethod("foo", model.W_CompiledMethod(0, ""))
+    assert m_class.lookup("foo").m_compiledin is m_super

Modified: pypy/dist/pypy/lang/smalltalk/test/test_primitives.py
==============================================================================
--- pypy/dist/pypy/lang/smalltalk/test/test_primitives.py	(original)
+++ pypy/dist/pypy/lang/smalltalk/test/test_primitives.py	Wed Oct 24 22:24:08 2007
@@ -1,12 +1,14 @@
 import py
 from pypy.lang.smalltalk.primitives import prim_table, PrimitiveFailedError
 import pypy.lang.smalltalk.primitives as p
-import pypy.lang.smalltalk.model as model
+from pypy.lang.smalltalk import model, mirror
 import pypy.lang.smalltalk.interpreter as interp
 import pypy.lang.smalltalk.classtable as ct
 import pypy.lang.smalltalk.fakeimage as fimg
 
-class MockFrame(interp.W_ContextFrame):
+mockclassmirror = ct.bootstrap_classmirror
+
+class MockFrame(interp.W_MethodContext):
     def __init__(self, stack):
         self.stack = stack
 
@@ -16,6 +18,7 @@
     if isinstance(x, model.W_Object): return x
     if isinstance(x, str) and len(x) == 1: return fimg.wrap_char(x)
     if isinstance(x, str): return fimg.wrap_string(x)
+    if isinstance(x, mirror.ClassMirror): return x.w_self
     raise NotImplementedError
     
 def mock(stack):
@@ -137,21 +140,21 @@
     assert prim(p.FLOAT_ADD, [3,4.5]).value == 7.5
 
 def test_at():
-    w_obj = model.W_Class(None, None, 0, format=model.VAR_POINTERS).new(1)
+    w_obj = mockclassmirror(0, varsized=True).new(1)
     w_obj.store(0, "foo")
     assert prim(p.AT, [w_obj, 0]) == "foo"
 
 def test_invalid_at():
-    w_obj = model.W_Class(None, None, 0, format=model.POINTERS).new()
+    w_obj = mockclassmirror(0).new()
     prim_fails(p.AT, [w_obj, 0])
 
 def test_at_put():
-    w_obj = model.W_Class(None, None, 0, format=model.VAR_POINTERS).new(1)
+    w_obj = mockclassmirror(0, varsized=1).new(1)
     assert prim(p.AT_PUT, [w_obj, 0, 22]).value == 22
     assert prim(p.AT, [w_obj, 0]).value == 22
     
 def test_invalid_at_put():
-    w_obj = model.W_Class(None, None, 0, format=model.POINTERS).new()
+    w_obj = mockclassmirror(0).new()
     prim_fails(p.AT_PUT, [w_obj, 0, 22])
 
 def test_string_at():
@@ -172,12 +175,12 @@
     prim_fails(p.OBJECT_AT, ["q", fimg.CHARACTER_VALUE_INDEX+1])
     
 def test_object_at_put():
-    w_obj = model.W_Class(None, None, 1, format=model.POINTERS).new()
+    w_obj = mockclassmirror(1).new()
     assert prim(p.OBJECT_AT_PUT, [w_obj, 0, "q"]) is wrap("q")
     assert prim(p.OBJECT_AT, [w_obj, 0]) is wrap("q")
 
 def test_invalid_object_at_put():
-    w_obj = model.W_Class(None, None, 1, format=model.POINTERS).new()
+    w_obj = mockclassmirror(1).new()
     prim_fails(p.OBJECT_AT, [w_obj, 1, 1])
     
 def test_string_at_put():
@@ -188,19 +191,19 @@
         assert prim(p.STRING_AT, [test_str, i]) == wrap(exp[i])
 
 def test_new():
-    w_res = prim(p.NEW, [ct.w_Object])
-    assert w_res.w_class == ct.w_Object
+    w_res = prim(p.NEW, [ct.m_Object])
+    assert w_res.getclassmirror() == ct.m_Object
     
 def test_invalid_new():
-    prim_fails(p.NEW, [ct.w_ByteString])
+    prim_fails(p.NEW, [ct.m_ByteString])
 
 def test_new_with_arg():
-    w_res = prim(p.NEW_WITH_ARG, [ct.w_ByteString, 20])
-    assert w_res.w_class == ct.w_ByteString
+    w_res = prim(p.NEW_WITH_ARG, [ct.m_ByteString, 20])
+    assert w_res.getclassmirror() == ct.m_ByteString
     assert w_res.size() == 20    
 
 def test_invalid_new_with_arg():
-    prim_fails(p.NEW_WITH_ARG, [ct.w_Object, 20])
+    prim_fails(p.NEW_WITH_ARG, [ct.m_Object, 20])
     
 def test_inst_var_at():
     # I am not entirely sure if this is what this primitive is
@@ -211,7 +214,7 @@
     assert w_v.value == ord("b")
 
 def test_as_oop():
-    w_obj = model.W_Class(None, None, 0, format=model.POINTERS).new()
+    w_obj = mockclassmirror(0).new()
     w_obj.w_hash = wrap(22)
     assert prim(p.AS_OOP, [w_obj]).value == 22
 



More information about the Pypy-commit mailing list