Author: Anton Gulenko <[email protected]>
Branch: storage
Changeset: r810:e958ff7ec197
Date: 2014-05-07 21:14 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/e958ff7ec197/

Log:    Implemented mustBeBoolean when sending a conditional jump message to
        a non-bool object. Added test, extended the test image. Cleaned up
        tracing functionality in interpreter.

diff --git a/images/running-something-mini.image 
b/images/running-something-mini.image
index 
ac12f8bf556e24ceb6046e03ef26d92e1e1201bf..e121d1f56f155c8c7184bb3dde82edcdbcc44d9a
GIT binary patch

[cut]

diff --git a/spyvm/constants.py b/spyvm/constants.py
--- a/spyvm/constants.py
+++ b/spyvm/constants.py
@@ -141,6 +141,7 @@
     "smalltalkdict" : SO_SMALLTALK,
     "display" : SO_DISPLAY_OBJECT,
     "doesNotUnderstand" : SO_DOES_NOT_UNDERSTAND,
+    "mustBeBoolean" : SO_MUST_BE_BOOLEAN,
     "interrupt_semaphore" : SO_USER_INTERRUPT_SEMAPHORE,
     "timerSemaphore" : SO_TIMER_SEMAPHORE,
 }
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -83,7 +83,7 @@
                     s_new_context = s_sender
                 s_new_context.push(nlr.value)
             except ProcessSwitch, p:
-                if self.tracing():
+                if self.trace:
                     print "====== Switch from: %s to: %s ======" % 
(s_new_context.short_str(), p.s_new_context.short_str())
                 s_new_context = p.s_new_context
 
@@ -169,21 +169,6 @@
         from rpython.rlib.rarithmetic import intmask
         return intmask(int((time.time() - self.startup_time) * 1000) & 
constants.TAGGED_MASK)
 
-    # ============== Methods for the tracing functionality ==============
-    
-    def padding(self, symbol=' '):
-        return symbol * (self.max_stack_depth - self.remaining_stack_depth)
-    
-    def tracing(self, check_conftest=False, primitives=False):
-        if not check_conftest:
-            return self.trace
-        if objectmodel.we_are_translated() or conftest.option is None:
-            return False
-        if primitives:
-            return conftest.option.prim_trace
-        else:
-            return conftest.option.bc_trace
-        
     # ============== Convenience methods for executing code ==============
     
     def interpret_toplevel(self, w_frame):
@@ -191,7 +176,7 @@
             self.loop(w_frame)
         except ReturnFromTopLevel, e:
             return e.object
-        
+
     def perform(self, w_receiver, selector, *arguments_w):
         if isinstance(selector, str):
             if selector == "asSymbol":
@@ -214,6 +199,9 @@
         self.interrupt_check_counter = self.interrupt_counter_size
         return self.interpret_toplevel(s_frame.w_self())
     
+    def padding(self, symbol=' '):
+        return symbol * (self.max_stack_depth - self.remaining_stack_depth)
+
 class ReturnFromTopLevel(Exception):
     _attrs_ = ["object"]
     def __init__(self, object):
@@ -358,17 +346,12 @@
 
     def _sendSelector(self, w_selector, argcount, interp,
                       receiver, receiverclassshadow):
-        if interp.tracing(check_conftest=True):
-            print "%sSending selector #%s to %r with: %r" % (
-                interp.padding(), w_selector.str_content(), receiver,
-                [self.peek(argcount-1-i) for i in range(argcount)])
         assert argcount >= 0
-
         try:
             w_method = receiverclassshadow.lookup(w_selector)
         except MethodNotFound:
             return self._doesNotUnderstand(w_selector, argcount, interp, 
receiver)
-
+        
         code = w_method.primitive()
         if code:
             try:
@@ -380,11 +363,25 @@
         self.pop() # receiver
 
         # 
######################################################################
-        if interp.tracing():
+        if interp.trace:
             print interp.padding() + s_frame.short_str()
 
         return interp.stack_frame(s_frame)
 
+    def _sendSpecialSelector(self, interp, receiver, special_selector, 
w_args=[]):
+        w_special_selector = self.space.objtable["w_" + special_selector]
+        s_class = receiver.class_shadow(self.space)
+        w_method = s_class.lookup(w_special_selector)
+        s_frame = w_method.create_frame(interp.space, receiver, w_args, self)
+        
+        # 
######################################################################
+        if interp.trace:
+            print '%s %s %s: #%s' % (interp.padding('#'), special_selector, 
s_frame.short_str(), w_args)
+            if not objectmodel.we_are_translated():
+                import pdb; pdb.set_trace()
+        
+        return interp.stack_frame(s_frame)
+    
     def _doesNotUnderstand(self, w_selector, argcount, interp, receiver):
         arguments = self.pop_and_return_n(argcount)
         w_message_class = self.space.classtable["w_Message"]
@@ -393,45 +390,36 @@
         w_message = s_message_class.new()
         w_message.store(self.space, 0, w_selector)
         w_message.store(self.space, 1, self.space.wrap_list(arguments))
-        s_class = receiver.class_shadow(self.space)
+        self.pop() # The receiver, already known.
+        
         try:
-            w_method = 
s_class.lookup(self.space.objtable["w_doesNotUnderstand"])
+            return self._sendSpecialSelector(interp, receiver, 
"doesNotUnderstand", [w_message])
         except MethodNotFound:
             from spyvm.shadow import ClassShadow
+            s_class = receiver.class_shadow(self.space)
             assert isinstance(s_class, ClassShadow)
-            print "Missing doesDoesNotUnderstand in hierarchy of %s" % 
s_class.getname()
+            print "Missing doesNotUnderstand in hierarchy of %s" % 
s_class.getname()
             raise
-        s_frame = w_method.create_frame(interp.space, receiver, [w_message], 
self)
-        self.pop()
-
-        # 
######################################################################
-        if interp.tracing():
-            print '%s%s missing: #%s' % (interp.padding('#'), 
s_frame.short_str(), w_selector.str_content())
-            if not objectmodel.we_are_translated():
-                import pdb; pdb.set_trace()
-
-        return interp.stack_frame(s_frame)
-
+    
+    def _mustBeBoolean(self, interp, receiver):
+        return self._sendSpecialSelector(interp, receiver, "mustBeBoolean")
+    
     def _call_primitive(self, code, interp, argcount, w_method, w_selector):
-        # the primitive pushes the result (if any) onto the stack itself
-        if interp.tracing(check_conftest=True):
-            print "%sActually calling primitive %d" % (interp.padding(), code,)
-        func = primitives.prim_holder.prim_table[code]
         # ##################################################################
-        if interp.tracing():
+        if interp.trace:
             print "%s-> primitive %d \t(in %s, named #%s)" % (
                     interp.padding(), code, 
self.w_method().get_identifier_string(), w_selector.str_content())
+        func = primitives.prim_holder.prim_table[code]
         try:
             # note: argcount does not include rcvr
+            # the primitive pushes the result (if any) onto the stack itself
             return func(interp, self, argcount, w_method)
         except primitives.PrimitiveFailedError, e:
-            if interp.tracing():
-                print "%s primitive FAILED" % interp.padding()
-            if interp.tracing(check_conftest=True, primitives=True):
-                print "PRIMITIVE FAILED: %d #%s" % (w_method.primitive, 
w_selector.str_content())
+            if interp.trace:
+                print "%s primitive %d FAILED\t (in %s, named %s)" % (
+                    interp.padding(), code, w_method.safe_identifier_string(), 
w_selector.str_content())
             raise e
 
-
     def _return(self, return_value, interp, s_return_to):
         # for tests, when returning from the top-level context
         if s_return_to is None:
@@ -439,7 +427,7 @@
         # unfortunately, the assert below is not true for some tests
         # assert self._stack_ptr == self.tempsize()
 
-        if interp.tracing():
+        if interp.trace:
             print '%s<- %s' % (interp.padding(), return_value.as_repr_string())
         raise Return(return_value, s_return_to)
 
@@ -642,10 +630,20 @@
     def jump(self, offset):
         self.store_pc(self.pc() + offset)
 
-    def jumpConditional(self,bool,position):
-        if self.top() == bool: # XXX this seems wrong?
+    def jumpConditional(self, interp, expecting_true, position):
+        if expecting_true:
+            w_expected = interp.space.w_true
+            w_alternative = interp.space.w_false
+        else:
+            w_alternative = interp.space.w_true
+            w_expected = interp.space.w_false
+        
+        # Don't check the class, just compare with only two instances.
+        w_bool = self.pop()
+        if w_expected.is_same_object(w_bool):
             self.jump(position)
-        self.pop()
+        elif not w_alternative.is_same_object(w_bool):
+            self._mustBeBoolean(interp, w_bool)
 
     def shortJumpPosition(self, current_bytecode):
         return (current_bytecode & 7) + 1
@@ -654,8 +652,8 @@
         self.jump(self.shortJumpPosition(current_bytecode))
 
     def shortConditionalJump(self, interp, current_bytecode):
-        self.jumpConditional(
-                interp.space.w_false, self.shortJumpPosition(current_bytecode))
+        # The conditional jump is "jump on false"
+        self.jumpConditional(interp, False, 
self.shortJumpPosition(current_bytecode))
 
     def longUnconditionalJump(self, interp, current_bytecode):
         self.jump((((current_bytecode & 7) - 4) << 8) + self.getbytecode())
@@ -664,11 +662,10 @@
         return ((current_bytecode & 3) << 8) + self.getbytecode()
 
     def longJumpIfTrue(self, interp, current_bytecode):
-        self.jumpConditional(interp.space.w_true, 
self.longJumpPosition(current_bytecode))
+        self.jumpConditional(interp, True, 
self.longJumpPosition(current_bytecode))
 
     def longJumpIfFalse(self, interp, current_bytecode):
-        self.jumpConditional(interp.space.w_false, 
self.longJumpPosition(current_bytecode))
-
+        self.jumpConditional(interp, False, 
self.longJumpPosition(current_bytecode))
 
     bytecodePrimAdd = make_call_primitive_bytecode(primitives.ADD, "+", 1)
     bytecodePrimSubtract = make_call_primitive_bytecode(primitives.SUBTRACT, 
"-", 1)
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
@@ -333,12 +333,23 @@
     assert isinstance(w_dnu, model.W_BytesObject)
     assert w_dnu.as_string() == "doesNotUnderstand:"
 
+def test_mustBeBoolean():
+    w_mbb = interp.space.objtable["w_mustBeBoolean"]
+    assert isinstance(w_mbb, model.W_BytesObject)
+    assert w_mbb.as_string() == "mustBeBoolean"
+    
 def test_run_doesNotUnderstand():
     space, interp, _, _ = read_image('running-something-mini.image')
     w_result = interp.perform(interp.space.wrap_int(0), "runningADNU")
     assert isinstance(w_result, model.W_BytesObject)
     assert w_result.as_string() == "foobarThis:doesNotExist:('pypy' 'heya' )"
 
+def test_run_mustBeBoolean():
+    space, interp, _, _ = read_image('running-something-mini.image')
+    w_result = interp.perform(interp.space.wrap_int(0), "runningMustBeBoolean")
+    assert isinstance(w_result, model.W_BytesObject)
+    assert w_result.as_string() == "mustBeBoolean has been called"
+    
 def test_Message():
     w_message_cls = interp.space.w_Message
     assert w_message_cls is interp.space.classtable["w_Message"]
@@ -349,13 +360,16 @@
     assert isinstance(w_message, model.W_PointersObject)
 
 def test_step_run_something():
+    # This test depends on the following code being executed in a workspace 
(the entire line):
+    # a := Smalltalk snapshotPrimitive. 1+2.
+    # This will save the image in a state that will satisfy the following test.
+    
     space, interp, _, _ = read_image('running-something-mini.image')
     ap = wrapper.ProcessWrapper(space, 
wrapper.scheduler(space).active_process())
     w_ctx = ap.suspended_context()
     s_ctx = w_ctx.as_context_get_shadow(space)
     ap.store_suspended_context(space.w_nil)
-
-    interp = TestInterpreter(space)
+    
     assert isinstance(s_ctx, shadow.MethodContextShadow)
     assert s_ctx.top().is_same_object(space.w_true)
     interp.step(s_ctx)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to