44For pictures, see ``doc/callcc_topology.pdf`` in the source distribution.
55"""
66
7- from ...syntax import macros , test # noqa: F401
7+ from ...syntax import macros , test , the # noqa: F401
88from ...test .fixtures import session , testset
99
1010from inspect import stack
@@ -17,6 +17,36 @@ def me():
1717 framerecord = callstack [1 ] # ignore me() itself, get caller's record
1818 return framerecord .function
1919
20+ # Continuation names are gensymmed, so `mcpyrate` adds a uuid to them.
21+ #
22+ # This makes it impossible to test that we get specifically, say, the
23+ # continuation function that represents the code after the nth `call_cc[]`
24+ # in a particular function.
25+ #
26+ # What we can do instead is map the human-readable `expected` name to the
27+ # actual gensymmed name the first time when a previously not seen continuation
28+ # name appears in the `expecteds` list. Any further appearances of the same
29+ # name in `expecteds` should map to the same actual gensymmed name.
30+ #
31+ def validate (results , expecteds ):
32+ seen_conts = {}
33+ def validate_one (result , expected ):
34+ if "_cont" in expected :
35+ if "_cont" not in result :
36+ return False
37+ if expected not in seen_conts : # New expected name; this cont should be new.
38+ if result in seen_conts .values (): # already seen?
39+ return False
40+ seen_conts [expected ] = result
41+ return True # it really was new, so assume everything is ok.
42+ # Already seen expected name; should correspond to the same
43+ # gensymmed name as before.
44+ return seen_conts [expected ] == result
45+ # For anything but continuations, match the exact names.
46+ return result == expected
47+ return all (validate_one (result , expected ) for result , expected in zip (results , expecteds ))
48+
49+
2050def runtests ():
2151 with testset ("basic case: one continuation" ):
2252 with continuations :
@@ -28,7 +58,7 @@ def f():
2858 call_cc [g ()]
2959 out .append (me ())
3060 f ()
31- test [out == ['f' , 'g' , 'f_cont' ]]
61+ test [validate ( the [ out ], ['f' , 'g' , 'f_cont' ]) ]
3262
3363 with testset ("sequence of continuations" ):
3464 with continuations :
@@ -44,7 +74,7 @@ def f():
4474 call_cc [h ()]
4575 out .append (me ())
4676 f ()
47- test [out == ['f' , 'g' , 'f_cont1' , 'h' , 'f_cont2' ]] # gensym -> cont1, ...
77+ test [validate ( the [ out ], ['f' , 'g' , 'f_cont1' , 'h' , 'f_cont2' ]) ] # gensym -> cont1, ...
4878
4979 with testset ("nested continuations, case 1" ): # left in the picture
5080 with continuations :
@@ -60,7 +90,7 @@ def f():
6090 call_cc [g ()]
6191 out .append (me ())
6292 f ()
63- test [out == ['f' , 'g' , 'h' , 'g_cont' , 'f_cont3' ]]
93+ test [validate ( the [ out ], ['f' , 'g' , 'h' , 'g_cont' , 'f_cont3' ]) ]
6494
6595 with testset ("nested continuations, case 2a, tail-call in f1" ): # right in the picture
6696 with continuations :
@@ -80,7 +110,7 @@ def f1(cc):
80110 def f2 (dummy ):
81111 out .append (me ())
82112 f1 (cc = f2 )
83- test [out == ['f1' , 'v' , 'w' , 'v_cont' , 'f2' ]]
113+ test [validate ( the [ out ], ['f1' , 'v' , 'w' , 'v_cont' , 'f2' ]) ]
84114
85115 with testset ("nested continuations, case 2b, call_cc in f1" ):
86116 with continuations :
@@ -98,7 +128,7 @@ def f1(cc):
98128 def f2 (dummy ):
99129 out .append (me ())
100130 f1 (cc = f2 )
101- test [out == ['f1' , 'v' , 'w' , 'v_cont1' , 'f1_cont' , 'f2' ]]
131+ test [validate ( the [ out ], ['f1' , 'v' , 'w' , 'v_cont1' , 'f1_cont' , 'f2' ]) ]
102132
103133 # preparation for confetti, create a saved chain
104134 with continuations :
@@ -126,7 +156,7 @@ def v(): # noqa: F811, the previous one is no longer used.
126156 call_cc [k ()]
127157 out .append (me ())
128158 v ()
129- test [out == ['v' , 'g_cont1' , 'f_cont4' , 'v_cont2' ]]
159+ test [validate ( the [ out ], ['v' , 'g_cont1' , 'f_cont4' , 'v_cont2' ]) ]
130160
131161 with testset ("confetti 1b - tail-calling a saved continuation" ):
132162 with continuations :
@@ -137,7 +167,7 @@ def f1():
137167 out .append (me ())
138168 return k (cc = f2 )
139169 f1 ()
140- test [out == ['f1' , 'g_cont1' , 'f_cont4' , 'f2' ]]
170+ test [validate ( the [ out ], ['f1' , 'g_cont1' , 'f_cont4' , 'f2' ]) ]
141171
142172 # more preparation for confetti
143173 with continuations :
@@ -183,7 +213,7 @@ def f1():
183213 out .append (me ())
184214 return k3 (cc = f2 )
185215 f1 ()
186- test [out == ['f1' , 'q_cont' , 'p_cont' , 's_cont' , 'r_cont' , 'f2' ]]
216+ test [validate ( the [ out ], ['f1' , 'q_cont' , 'p_cont' , 's_cont' , 'r_cont' , 'f2' ]) ]
187217
188218 # more preparation for confetti
189219 with continuations :
@@ -213,7 +243,7 @@ def f1():
213243 out .append (me ())
214244 return k4 (cc = f2 )
215245 f1 ()
216- test [out == ['f1' , 'y_cont' , 's_cont' , 'r_cont' , 'x_cont' , 'f2' ]]
246+ test [validate ( the [ out ], ['f1' , 'y_cont' , 's_cont' , 'r_cont' , 'x_cont' , 'f2' ]) ]
217247
218248if __name__ == '__main__' : # pragma: no cover
219249 with session (__file__ ):
0 commit comments