2 # Copyright (C) 2006-2008, Parrot Foundation.
7 t/library/coroutine.t -- Test the Parrot::Coroutine class
11 ./parrot t/library/coroutine.t
15 This script tests the C<Parrot::Coroutine> class using an implementation of the
16 "same fringe" problem.
18 Note: In order to see how coroutine calling works in detail, insert
19 C<trace 4> before and C<trace 0> after one of the C<same_fringe> calls
20 in the body of the main program.
24 L<http://swiss.csail.mit.edu/classes/symbolic/spring06/psets/ps6/samefringe.scm>
25 -- a collection of "same fringe" implementations in Scheme.
29 .const int N_TESTS = 6
33 ## Build an N-ary tree (where N is passed as node_width) of the specified depth,
34 ## with the leaves being consecutive integer PMCs from start but less than N.
35 ## The tree will be complete iff end-start+1 == node_width^depth.
49 result = new 'ResizablePMCArray'
54 if i >= node_width goto done
55 if start > end goto done
56 ($P0, start) = make_nary_tree(start, end, node_width, depth)
61 .return (result, start)
64 ## non-coroutine traversal, for debugging.
67 .param int depth :optional
68 .param int depth_p :opt_flag
70 if depth_p goto have_depth
75 $I0 = isa tree_node, 'ResizablePMCArray'
84 ## Loop through array elements, recurring on each.
89 if i >= size goto done
90 print "[recur: depth "
96 enumerate_tree($P1, depth)
101 ## Recursive coroutine to enumerate tree elements. Each element that is not a
102 ## FixedPMCArray is yielded in turn.
103 .sub coro_enumerate_tree
106 .param int depth :optional
107 .param int depth_p :opt_flag
109 if depth_p goto have_depth
114 $I0 = isa tree_node, 'FixedPMCArray'
119 coro.'yield'(tree_node)
123 ## Loop through array elements, recurring on each.
128 if i >= size goto done
129 ## print "[coro recur: depth "
135 coro_enumerate_tree(coro, $P1, depth)
142 ## Solution to the "same fringe" problem that uses coroutines to enumerate each
143 ## of two passed trees of numbers. Returns 1 if the trees have the same fringe,
149 .local pmc coro_class
150 coro_class = get_class ['Parrot'; 'Coroutine']
151 unless null coro_class goto found
152 printerr "Bug: Can't find ['Parrot'; 'Coroutine'] class.\n"
155 .local pmc coro1, coro2
156 .const 'Sub' coro_sub = "coro_enumerate_tree"
157 coro1 = coro_class.'new'('initial_sub' => coro_sub)
158 coro2 = coro_class.'new'('initial_sub' => coro_sub)
159 ($P0 :optional, $I0 :opt_flag) = coro1.'resume'(coro1, tree1)
160 ($P1 :optional, $I1 :opt_flag) = coro2.'resume'(coro2, tree2)
163 if $I0 goto got_first
164 if $I1 goto not_equal
167 unless $I1 goto not_equal
169 ## now have results from both.
175 if $P0 != $P1 goto not_equal
176 ## set up for the next iteration.
177 ($P0 :optional, $I0 :opt_flag) = coro1.'resume'()
178 ($P1 :optional, $I1 :opt_flag) = coro2.'resume'()
187 load_bytecode 'Test/Builder.pbc'
189 test = new [ 'Test'; 'Builder' ]
193 load_bytecode 'Parrot/Coroutine.pbc'
195 test.'ok'(1, 'loaded bytecode')
197 ## grow some trees for traversal.
198 .local pmc binary, binary_4, ternary, ternary_2
199 binary = make_nary_tree(1, 8, 2, 3)
200 ternary = make_nary_tree(1, 8, 3, 2)
201 binary_4 = make_nary_tree(1, 16, 2, 4)
202 ## now make a "damaged" one that will be different.
203 ternary_2 = make_nary_tree(1, 8, 3, 2)
207 ## enumerate_tree(ternary_2)
208 test.'ok'(1, 'made test trees.')
210 $I0 = same_fringe(binary, binary)
211 test.'ok'($I0, 'binary [[[1,2],[3,4]],[[5,6],[7,8]]] vs. itself')
212 $I0 = same_fringe(binary, binary_4)
214 test.'ok'($I0, 'binary 1..8 vs. binary 1..16')
215 $I0 = same_fringe(binary, ternary)
216 test.'ok'($I0, 'binary 1..8 vs. ternary [[1,2,3],[4,5,6],[7,8]]')
217 $I0 = same_fringe(binary, ternary_2)
219 test.'ok'($I0, 'binary 1..8 vs. ternary [[1,2,3],4,[7,8]]')
223 test.'ok'(0, 'Load failed')
231 # vim: expandtab shiftwidth=4 ft=pir: