[pypy-svn] r30853 - in pypy/dist/pypy: lib module/_stackless objspace/cclp objspace/test
auc at codespeak.net
auc at codespeak.net
Tue Aug 1 17:37:41 CEST 2006
Author: auc
Date: Tue Aug 1 17:37:37 2006
New Revision: 30853
Modified:
pypy/dist/pypy/lib/_exceptions.py
pypy/dist/pypy/module/_stackless/clonable.py
pypy/dist/pypy/module/_stackless/interp_clonable.py
pypy/dist/pypy/objspace/cclp/scheduler.py
pypy/dist/pypy/objspace/cclp/types.py
pypy/dist/pypy/objspace/cclp/variable.py
pypy/dist/pypy/objspace/test/test_logicobjspace.py
Log:
proper exceptions types are now raised
futures read-onlyness more correctly enforced
Modified: pypy/dist/pypy/lib/_exceptions.py
==============================================================================
--- pypy/dist/pypy/lib/_exceptions.py (original)
+++ pypy/dist/pypy/lib/_exceptions.py Tue Aug 1 17:37:37 2006
@@ -436,3 +436,16 @@
badchar, self.start, self.reason)
return "%r codec can't encode characters in position %d-%d: %s" % (
self.encoding, self.start, self.end - 1, self.reason)
+
+
+
+#-- Logic object space specific stuff
+#XXX conditionalize me on '-o logic'
+
+class LOError(Exception): pass
+
+class UnificationError(LOError): pass
+class RebindingError(LOError): pass
+class FutureBindingError(LOError): pass
+
+class AllBlockedError(LOError): pass
Modified: pypy/dist/pypy/module/_stackless/clonable.py
==============================================================================
--- pypy/dist/pypy/module/_stackless/clonable.py (original)
+++ pypy/dist/pypy/module/_stackless/clonable.py Tue Aug 1 17:37:37 2006
@@ -57,7 +57,7 @@
raise OperationError(space.w_ValueError, space.wrap(
"cannot switch to an unbound Coroutine"))
self.switch()
- rstack.resume_point("w_switch", self, space)
+ #rstack.resume_point("w_switch", self, space)
state = self.costate
w_ret, state.w_tempval = state.w_tempval, space.w_None
return w_ret
Modified: pypy/dist/pypy/module/_stackless/interp_clonable.py
==============================================================================
--- pypy/dist/pypy/module/_stackless/interp_clonable.py (original)
+++ pypy/dist/pypy/module/_stackless/interp_clonable.py Tue Aug 1 17:37:37 2006
@@ -4,7 +4,6 @@
from pypy.interpreter.error import OperationError
-from pypy.rpython import rstack # for resume points
from pypy.tool import stdlib_opcode as pythonopcode
class InterpClonableCoroutine(Coroutine):
Modified: pypy/dist/pypy/objspace/cclp/scheduler.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/scheduler.py (original)
+++ pypy/dist/pypy/objspace/cclp/scheduler.py Tue Aug 1 17:37:37 2006
@@ -126,7 +126,7 @@
self._init_head(self._main)
self._init_blocked()
w(".. SCHEDULER reinitialized")
- raise OperationError(self.space.w_RuntimeError,
+ raise OperationError(self.space.w_AllBlockedError,
self.space.wrap("can't schedule, possible deadlock in sight"))
return to_be_run
Modified: pypy/dist/pypy/objspace/cclp/types.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/types.py (original)
+++ pypy/dist/pypy/objspace/cclp/types.py Tue Aug 1 17:37:37 2006
@@ -1,10 +1,10 @@
-from pypy.interpreter import baseobjspace
+from pypy.interpreter import baseobjspace, typedef
from pypy.objspace.cclp.misc import w, ClonableCoroutine
W_Root = baseobjspace.W_Root
-#-- Types --------------------------------------------------
+#-- Variables types ----------------------------------------
class W_Var(W_Root):
def __init__(w_self, space):
@@ -27,15 +27,16 @@
w_self.client = ClonableCoroutine.w_getcurrent(space)
w("FUT", str(w_self))
+#-- Exception types ----------------------------------------
-class W_FailedValue(W_Root, object):
+class W_FailedValue(W_Root):
"""wraps an exception raised in some coro, to be re-raised in
some dependant coro sometime later
"""
def __init__(w_self, exc):
w_self.exc = exc
-#-- Misc ----------------------------------------------------
+#-- Misc ---------------------------------------------------
def deref(space, w_var):
#XXX kill me ?
Modified: pypy/dist/pypy/objspace/cclp/variable.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/variable.py (original)
+++ pypy/dist/pypy/objspace/cclp/variable.py Tue Aug 1 17:37:37 2006
@@ -55,7 +55,7 @@
scheduler[0].add_to_blocked_byneed(w_var, ClonableCoroutine.w_getcurrent(space))
scheduler[0].schedule()
else:
- raise OperationError(space.w_RuntimeError,
+ raise OperationError(space.w_TypeError,
space.wrap("wait_needed only supported on unbound variables"))
def wait_needed(space, w_var):
@@ -140,18 +140,21 @@
w_curr = w_next
-def fail(space, w_obj1, w_obj2):
+def raise_unification_failure(space):
"""raises a specific exception for bind/unify
should fail the current comp. space at some point"""
- #FIXME : really raise some specific exception
- assert isinstance(w_obj1, W_Root)
- assert isinstance(w_obj2, W_Root)
- raise OperationError(space.w_RuntimeError,
+ raise OperationError(space.w_UnificationError,
space.wrap("Unification failure"))
+# to signal a future binding exception
+def raise_future_binding(space):
+ raise OperationError(space.w_FutureBindingError,
+ space.wrap("This future is read-only for you, pal"))
+
#-- BIND -----------------------------
+
def bind(space, w_var, w_obj):
"""1. aliasing of unbound variables
2. assign bound var to unbound var
@@ -170,15 +173,15 @@
return _assign(space, w_var, w_obj)
if space.is_true(space.eq(w_var.w_bound_to, w_obj)):
return
- raise OperationError(space.w_RuntimeError,
- space.wrap("Cannot bind twice"))
+ raise OperationError(space.w_RebindingError,
+ space.wrap("Cannot bind twice but two identical values"))
+
def bind__Future_Root(space, w_fut, w_obj):
#v("future val", str(id(w_fut)))
if w_fut.client == ClonableCoroutine.w_getcurrent(space):
- raise OperationError(space.w_RuntimeError,
- space.wrap("This future is read-only for you, pal"))
- bind__Var_Root(space, w_fut, w_obj) # call-next-method ?
+ raise_future_binding(space)
+ return bind__Var_Root(space, w_fut, w_obj) # call-next-method ?
def bind__Var_Var(space, w_v1, w_v2):
#w("var var")
@@ -199,17 +202,20 @@
def bind__Future_Var(space, w_fut, w_var):
#v("future var")
if w_fut.client == ClonableCoroutine.w_getcurrent(space):
- raise OperationError(space.w_RuntimeError,
- space.wrap("This future is read-only for you, pal"))
- bind__Var_Var(space, w_fut, w_var)
+ raise_future_binding(space)
+ return bind__Var_Var(space, w_fut, w_var)
-#XXX Var_Future would just alias or assign, this is ok
+def bind__Var_Future(space, w_var, w_fut):
+ if space.is_true(space.is_bound(w_fut)):
+ return bind__Var_Root(w_var, w_fut.w_bound_to)
+ raise_future_binding(space)
bind_mm = StdObjSpaceMultiMethod('bind', 2)
bind_mm.register(bind__Var_Root, W_Var, W_Root)
bind_mm.register(bind__Var_Var, W_Var, W_Var)
bind_mm.register(bind__Future_Root, W_Future, W_Root)
bind_mm.register(bind__Future_Var, W_Future, W_Var)
+bind_mm.register(bind__Var_Future, W_Var, W_Future)
all_mms['bind'] = bind_mm
def _assign(space, w_var, w_val):
@@ -281,7 +287,7 @@
w_d1 = w_x.getdict() #returns wrapped dict or unwrapped None ...
w_d2 = w_y.getdict()
if None in [w_d1, w_d2]:
- fail(space, w_x, w_y)
+ raise_unification_failure(space)
else:
return space.unify(w_d1, w_d2)
return space.w_None
@@ -308,7 +314,7 @@
def unify__Tuple_Tuple(space, w_i1, w_i2):
if len(w_i1.wrappeditems) != len(w_i2.wrappeditems):
- fail(space, w_i1, w_i2)
+ raise_unification_failure(space)
idx, top = (-1, space.int_w(space.len(w_i1))-1)
while idx < top:
idx += 1
@@ -321,7 +327,7 @@
def unify__List_List(space, w_i1, w_i2):
if len(w_i1.wrappeditems) != len(w_i2.wrappeditems):
- fail(space, w_i1, w_i2)
+ raise_unification_failure(space)
idx, top = (-1, space.int_w(space.len(w_i1))-1)
while idx < top:
idx += 1
Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original)
+++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Tue Aug 1 17:37:37 2006
@@ -17,7 +17,7 @@
assert is_bound(1)
# FIXME : propagate proper
# FailureException
- raises(Exception, bind, X, 2)
+ raises(RebindingError, bind, X, 2)
def test_bind_to_self(self):
X = newvar()
@@ -51,7 +51,6 @@
assert alias_of(X, Y)
assert alias_of(X, Y)
unify(X, 1)
- # what about is_alias, then ?
assert X == 1
assert Y == 1
@@ -131,7 +130,7 @@
X = newvar()
def f(x):
return x + 1
- raises(Exception, f, X)
+ raises(AllBlockedError, f, X)
def test_eq_unifies_simple(self):
X = newvar()
@@ -171,7 +170,7 @@
unify(X, (1, (2, None)))
assert X == (1, (2, None))
unify(X, (1, (2, None)))
- raises(Exception, unify, X, (1, 2))
+ raises(UnificationError, unify, X, (1, 2))
def test_unify_dict(self):
Z, W = newvar(), newvar()
@@ -193,7 +192,7 @@
assert alias_of(f1.b, f2.b)
unify(f2.b, 'foo')
assert f1.b == f2.b == 'foo'
- raises(Exception, unify, f1.b, 24)
+ raises(UnificationError, unify, f1.b, 24)
class AppTest_LogicFutures(object):
@@ -202,8 +201,6 @@
cls.space = gettestobjspace('logic', usemodules=("_stackless",))
def test_future_value(self):
- print "future value", sched_info()
-
def poop(X):
return X + 1
@@ -214,22 +211,18 @@
X = newvar()
T = future(poop, X)
- raises(Exception, unify, T, 42)
+ raises(FutureBindingError, unify, T, 42)
bind(X, 42); schedule() # helps the gc
- X, Y = newvar(), newvar()
+ X, Y, Z = newvar(), newvar(), newvar()
+ bind(Z, 42)
T = future(poop, X)
- raises(Exception, unify, T, Y)
+ raises(FutureBindingError, unify, T, Z)
+ raises(FutureBindingError, unify, Z, T)
+ raises(FutureBindingError, unify, Y, T)
+ raises(FutureBindingError, unify, T, Y)
bind(X, 42); schedule() # gc ...
- assert is_free(Y)
- X = newvar()
- T = future(poop, X)
- unify(Y, T)
- unify(X, 42)
- assert Y == 43
- bind(X, 42); schedule()
-
def test_one_future_exception(self):
print "one future exception", sched_info()
class FooException(Exception): pass
@@ -340,22 +333,26 @@
def test_eager_producer_consummer(self):
print "eager_producer_consummer", sched_info()
- def generate(n, limit):
+ def generate(n, limit, R):
if n < limit:
- return (n, generate(n + 1, limit))
- return None
+ Tail = newvar()
+ unify(R, (n, Tail))
+ return generate(n + 1, limit, Tail)
+ bind(R, None)
+ return
- def sum(L, a):
+ def sum(L, a, R):
Head, Tail = newvar(), newvar()
unify(L, (Head, Tail))
if Tail != None:
- return sum(Tail, Head + a)
- return a + Head
+ return sum(Tail, Head + a, R)
+ bind(R, a + Head)
+ return
X = newvar()
S = newvar()
- unify(S, future(sum, X, 0))
- unify(X, future(generate, 0, 10))
+ stacklet(sum, X, 0, S)
+ stacklet(generate, 0, 10, X)
assert S == 45
@@ -365,28 +362,32 @@
def lgenerate(n, L):
"""wait-needed version of generate"""
#XXX how is this ever collected ?
+ # should be when L becomes unreferenced from
+ # outside this thread ... But this can't
+ # happen right now because we keep
+ # references also of this thread in the
+ # scheduler.
wait_needed(L)
Tail = newvar()
bind(L, (n, Tail))
lgenerate(n+1, Tail)
- def lsum(L, a, limit):
+ def lsum(L, a, limit, R):
"""this summer controls the generator"""
if limit > 0:
Head, Tail = newvar(), newvar()
- wait(L)
+ wait(L) # send needed signal to generator
unify(L, (Head, Tail))
- return lsum(Tail, a+Head, limit-1)
+ return lsum(Tail, a+Head, limit-1, R)
else:
- return a
+ bind(R, a)
Y = newvar()
T = newvar()
future(lgenerate, 0, Y)
- unify(T, future(lsum, Y, 0, 10))
+ stacklet(lsum, Y, 0, 10, T)
- wait(T)
assert T == 45
assert len(sched_info()['blocked_byneed']) == 1
reset_scheduler()
More information about the Pypy-commit
mailing list