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