[pypy-svn] rev 901 - in pypy/trunk/src/pypy: interpreter objspace/ann objspace/ann/test tool
gvanrossum at codespeak.net
gvanrossum at codespeak.net
Sun Jun 22 11:36:29 CEST 2003
Author: gvanrossum
Date: Sun Jun 22 11:36:28 2003
New Revision: 901
Added:
pypy/trunk/src/pypy/objspace/ann/cloningcontext.py (contents, props changed)
Modified:
pypy/trunk/src/pypy/interpreter/baseobjspace.py
pypy/trunk/src/pypy/interpreter/executioncontext.py
pypy/trunk/src/pypy/interpreter/pyframe.py
pypy/trunk/src/pypy/objspace/ann/objspace.py
pypy/trunk/src/pypy/objspace/ann/test/test_simple.py
pypy/trunk/src/pypy/tool/methodChecker.py (props changed)
Log:
Clone the frame when in indeterminate 'if' is found.
Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original)
+++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Sun Jun 22 11:36:28 2003
@@ -50,9 +50,13 @@
"Return what we consider to be the active execution context."
ec = threadlocals.getlocals().executioncontext
if ec is None:
- ec = ExecutionContext(self)
+ ec = self.createexecutioncontext()
return ec
+ def createexecutioncontext(self):
+ "Factory function for execution contexts."
+ return ExecutionContext(self)
+
def gethelper(self, applicationfile):
try:
helper = self.appfile_helpers[applicationfile]
Modified: pypy/trunk/src/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/executioncontext.py (original)
+++ pypy/trunk/src/pypy/interpreter/executioncontext.py Sun Jun 22 11:36:28 2003
@@ -226,6 +226,11 @@
def empty(self):
return not self.items
+ def clone(self):
+ s = Stack()
+ s.items = self.items[:]
+ return s
+
# installing the excepthook for OperationErrors
def operr_excepthook(exctype, value, traceback):
Modified: pypy/trunk/src/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyframe.py (original)
+++ pypy/trunk/src/pypy/interpreter/pyframe.py Sun Jun 22 11:36:28 2003
@@ -30,6 +30,16 @@
self.last_exception = None
self.next_instr = 0
+ def clone(self):
+ f = PyFrame(self.space, self.bytecode, self.w_globals, self.w_locals)
+ f.valuestack = self.valuestack.clone()
+ f.blockstack = self.blockstack.clone()
+ f.last_exception = self.last_exception
+ f.next_instr = self.next_instr
+ # Clone the locals (only the annotation space implements this)
+ f.w_locals = self.space.clone_locals(self.w_locals)
+ return f
+
def eval(self, executioncontext):
"Interpreter main loop!"
from pypy.interpreter import opcode
@@ -60,7 +70,7 @@
except ControlFlowException, ctlflowexc:
# we have a reason to change the control flow
# (typically unroll the stack)
- ctlflowexc.action(self)
+ ctlflowexc.action(self, last_instr)
except ExitFrame, e:
# leave that frame
@@ -251,7 +261,7 @@
WHY_YIELD SYieldValue
"""
- def action(self, frame):
+ def action(self, frame, last_instr):
"Default unroller implementation."
try:
while not frame.blockstack.empty():
@@ -292,7 +302,7 @@
class SYieldValue(ControlFlowException):
"""Signals a 'yield' statement.
Argument is the wrapped object to return."""
- def action(self, frame):
+ def action(self, frame, last_instr):
# XXX generators
raise OperationError(frame.space.w_Exception,
frame.space.wrap("generators are not ready yet"))
Added: pypy/trunk/src/pypy/objspace/ann/cloningcontext.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/objspace/ann/cloningcontext.py Sun Jun 22 11:36:28 2003
@@ -0,0 +1,44 @@
+from pypy.interpreter.executioncontext import ExecutionContext
+from pypy.interpreter.pyframe import ControlFlowException
+
+class IndeterminateCondition(ControlFlowException):
+
+ def __init__(self, w_obj):
+ ControlFlowException.__init__(self)
+ self.w_obj = w_obj
+
+ def action(self, frame, last_instr):
+ frame.next_instr = last_instr
+ f2 = frame.clone()
+ clones = frame.clones
+ clones.append(f2)
+ f2.clones = clones # Share the joy
+ f2.force_w_obj = self.w_obj
+ self.w_obj.force = True
+
+class CloningExecutionContext(ExecutionContext):
+
+ lastframe = None
+
+ def bytecode_trace(self, frame):
+ self.lastframe = frame
+
+ def eval_frame(self, frame):
+ from pypy.objspace.ann.objspace import W_Anything
+ assert not hasattr(frame, "clones")
+ space = frame.space
+ clones = [frame]
+ frame.clones = clones
+ frame.force_w_obj = None
+ result = None # W_Impossible
+ while clones:
+ f = clones.pop()
+ w_obj = f.force_w_obj
+ if w_obj is not None:
+ assert w_obj.force == True
+ w_obj.force = False
+ r = ExecutionContext.eval_frame(self, f)
+ result = space.union(result, r)
+ if isinstance(result, W_Anything):
+ break
+ return result
Modified: pypy/trunk/src/pypy/objspace/ann/objspace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/ann/objspace.py (original)
+++ pypy/trunk/src/pypy/objspace/ann/objspace.py Sun Jun 22 11:36:28 2003
@@ -4,6 +4,8 @@
from pypy.interpreter.baseobjspace \
import ObjSpace, OperationError, NoValue, PyPyError
from pypy.interpreter.pycode import PyByteCode
+from pypy.objspace.ann.cloningcontext import CloningExecutionContext
+from pypy.objspace.ann.cloningcontext import IndeterminateCondition
class W_Object(object):
@@ -28,11 +30,20 @@
return len(self.args_w)
def __getitem__(self, i):
return self.args_w[i]
+ def clone(self):
+ args_w = self.args_w
+ if isinstance(args_w, dict):
+ args_w = args_w.copy()
+ # XXX Recurse down the values?
+ return W_KnownKeysContainer(args_w)
class AnnException(Exception):
pass
+class UnwrapException(AnnException):
+ pass
+
class AnnotationObjSpace(ObjSpace):
@@ -48,7 +59,7 @@
setattr(self, 'w_' + c.__name__, self.wrap(c))
self.w_builtins = self.wrap(__builtin__)
- # Service methods
+ # Service methods whose interface is in the abstract base class
def wrap(self, obj):
return W_Constant(obj)
@@ -57,21 +68,59 @@
if isinstance(w_obj, W_Constant):
return w_obj.value
elif isinstance(w_obj, W_Object):
- raise AnnException, "Cannot unwrap %r" % w_obj
+ raise UnwrapException("Cannot unwrap: " +repr(w_obj))
else:
- raise TypeError, "not wrapped: %s" % repr(w_obj)
-
- def is_true(self, w_obj):
- if isinstance(w_obj, W_KnownKeysContainer):
- return bool(len(w_obj))
- obj = self.unwrap(w_obj)
- return bool(obj)
+ raise TypeError("not wrapped: " + repr(w_obj))
def reraise(self):
t, v = sys.exc_info()[:2]
raise OperationError(self.wrap(t), self.wrap(v))
- # Specialized creators
+ def is_true(self, w_obj):
+ if hasattr(w_obj, "force"):
+ return w_obj.force # Forced by cloning machinery
+ if isinstance(w_obj, W_KnownKeysContainer):
+ return bool(len(w_obj))
+ try:
+ obj = self.unwrap(w_obj)
+ except UnwrapException:
+ pass
+ else:
+ return bool(obj)
+ # It's indeterminate!!! Aargh!!!
+ # Raise an exception that will clone the interpreter.
+ raise IndeterminateCondition(w_obj)
+
+ def createexecutioncontext(self):
+ return CloningExecutionContext(self)
+
+ def clone_locals(self, w_locals):
+ assert isinstance(w_locals, W_KnownKeysContainer)
+ return w_locals.clone()
+
+ def union(self, r1, r2):
+ # Unite two results
+ if r1 is r2:
+ return r1
+ if r1 is None:
+ return r2
+ if r2 is None:
+ return r1
+ if isinstance(r1, W_Anything) or isinstance(r2, W_Anything):
+ return W_Anything()
+ if (isinstance(r1, W_Constant) and isinstance(r2, W_Constant) and
+ r1.value == r2.value):
+ return W_Constant(r1.value)
+ if self.is_int(r1) and self.is_int(r2):
+ return W_Integer()
+ if (isinstance(r1, W_KnownKeysContainer) and
+ isinstance(r2, W_KnownKeysContainer) and
+ r1.args_w == r2.args_w):
+ return W_KnownKeysContainer(r1.args_w)
+ # XXX Could do more cases. This will blow up as we add more types
+ return W_Anything()
+
+ # Specialized creators whose interface is in the abstract base class
def newtuple(self, args_w):
for w_arg in args_w:
@@ -84,7 +133,7 @@
for w_key, w_value in items_w:
try:
key = self.unwrap(w_key)
- except AnnException:
+ except UnwrapException:
break
else:
values_w[key] = w_value
@@ -105,7 +154,7 @@
try:
left = self.unwrap(w_left)
right = self.unwrap(w_right)
- except AnnException:
+ except UnwrapException:
pass
else:
return self.wrap(left + right)
@@ -141,7 +190,7 @@
try:
obj = self.unwrap(w_obj)
name = self.unwrap(w_name)
- except AnnException:
+ except UnwrapException:
return W_Anything()
else:
try:
@@ -154,7 +203,7 @@
return self.wrap(len(w_obj))
try:
obj = self.unwrap(w_obj)
- except AnnException:
+ except UnwrapException:
return W_Anything()
else:
return self.wrap(len(obj))
@@ -162,11 +211,11 @@
def getitem(self, w_obj, w_key):
try:
key = self.unwrap(w_key)
- except AnnException:
+ except UnwrapException:
return W_Anything()
try:
obj = self.unwrap(w_obj)
- except AnnException:
+ except UnwrapException:
if isinstance(w_obj, W_KnownKeysContainer):
return w_obj[key]
else:
Modified: pypy/trunk/src/pypy/objspace/ann/test/test_simple.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/ann/test/test_simple.py (original)
+++ pypy/trunk/src/pypy/objspace/ann/test/test_simple.py Sun Jun 22 11:36:28 2003
@@ -2,23 +2,23 @@
from pypy.tool import test
from pypy.objspace.ann.objspace import W_Object, W_Anything, W_Integer
from pypy.objspace.ann.objspace import AnnotationObjSpace
-from pypy.interpreter import baseobjspace, executioncontext, pyframe
+from pypy.interpreter import baseobjspace, pyframe
class TestAnnotationObjSpace(test.TestCase):
def codetest(self, source, functionname, args_w):
"""Compile and run the given code string, and then call its function
named by 'functionname' with a list of wrapped arguments 'args_w'.
- It returns the wrapped result."""
+ Return the wrapped result."""
glob = {}
exec source in glob
+ func = glob[functionname]
- space = self.space
- w_args = space.newtuple(args_w)
- w_func = space.wrap(glob[functionname])
- w_kwds = space.newdict([])
- return space.call(w_func, w_args, w_kwds)
+ w_args = self.space.newtuple(args_w)
+ w_func = self.space.wrap(func)
+ w_kwds = self.space.newdict([])
+ return self.space.call(w_func, w_args, w_kwds)
def setUp(self):
self.space = AnnotationObjSpace()
@@ -47,6 +47,24 @@
'f', [W_Integer()])
self.assertEquals(type(x), W_Integer)
+ def test_conditional_1(self):
+ x = self.codetest("def f(i):\n"
+ " if i < 0:\n"
+ " return 0\n"
+ " else:\n"
+ " return 1\n",
+ 'f', [W_Integer()])
+ self.assertEquals(type(x), W_Integer)
+
+ def test_conditional_2(self):
+ x = self.codetest("def f(i):\n"
+ " if i < 0:\n"
+ " return 0\n"
+ " else:\n"
+ " return 0\n",
+ 'f', [W_Integer()])
+ self.assertEquals(self.space.unwrap(x), 0)
+
if __name__ == '__main__':
More information about the Pypy-commit
mailing list