File: continuations.t

package info (click to toggle)
nqp 2022.12%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,436 kB
  • sloc: java: 28,030; perl: 3,394; ansic: 451; makefile: 200; javascript: 68; sh: 1
file content (117 lines) | stat: -rw-r--r-- 3,317 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# continuations.

plan(14);

{
    # unique objects
    my $A := "A";
    my $B := "B";

    my int $run;
    my $res := nqp::continuationreset(nqp::null(), {
        $run++;
        42;
    });

    ok($run == 1, 'reset runs argument once');
    ok($res == 42, 'reset passes return value');

    my $ex := '';
    $run := 0;

    my str $log := '';
    $log := $log ~ 1;
    my $savecont;
    my $shift_returned;

    my $reset_returned := nqp::continuationreset(nqp::null(), {
        $log := $log ~ 2;
        $shift_returned := nqp::continuationcontrol(0, nqp::null(), -> $cont {
            $log := $log ~ 3;
            $savecont := $cont;
            10;
        });
        $log := $log ~ 4;
        $shift_returned * 2;
    });
    ok( $log eq '123', 'control returns from reset' );
    ok( $savecont, 'got a continuation' );

    ok( $reset_returned == 10, 'shift argument return value is reset return value' );

    $log := '';
    $reset_returned := nqp::continuationinvoke($savecont, { $log := $log ~ '5'; 15 });
    ok( $log eq '54', 'continuation invoke "returns" from control');
    ok( $shift_returned == 15, 'continuation invoke argument is shift return value' );
    ok( $reset_returned == 30, 'reset block return value is continuation invoke return value' );

}

{
    my $log := '';

    my $next;
    nqp::continuationreset(nqp::null(), {
        $log := $log ~ 1;
        nqp::continuationcontrol(0, nqp::null(), -> $cont { $next := $cont });
        $log := $log ~ 2;
        nqp::continuationcontrol(0, nqp::null(), -> $cont { $next := $cont });
        $log := $log ~ 3;
        nqp::continuationcontrol(0, nqp::null(), -> $cont { $next := $cont });
        $log := $log ~ 4;
        777;
    });

    is($log, '1', 'passing a continuation to nqp::continuationreset 1/4');
    nqp::continuationreset(nqp::null(), $next);
    is($log, '12', 'passing a continuation to nqp::continuationreset 2/4');
    nqp::continuationreset(nqp::null(), $next);
    is($log, '123', 'passing a continuation to nqp::continuationreset 3/4');
    my $ret := nqp::continuationreset(nqp::null(), $next);
    is($log, '1234', 'passing a continuation to nqp::continuationreset 4/4');
    is($ret, 777, 'passing a continuation to nqp::continuationreset - correct return value');
}



# gather/take example
{
    my $SENTINEL := [];
    sub yield($value) {
        nqp::continuationcontrol(0, nqp::null(), -> $dcont {
            [$value, { nqp::continuationinvoke($dcont, {0}) }]
        });
    }

    sub start_iter($body) {
        my $state := { $body(); yield($SENTINEL) };
        -> {
            my $pkt := nqp::continuationreset(nqp::null(), $state);
            $state := $pkt[1];
            $pkt[0];
        }
    }

    sub mktree($l,$base) {
        $l ?? [ mktree($l-1,$base~0), mktree($l-1,$base~1) ] !! $base;
    }

    sub walktree($tree) {
        if nqp::istype($tree, NQPArray) {
            for $tree { walktree($_) }
        } else {
            yield($tree);
        }
    }

    sub uniter($block) {
        my $iter := start_iter($block);
        my $rv;
        my @list;
        until ($rv := $iter()) =:= $SENTINEL { nqp::push(@list, $rv); }
        nqp::join('~',@list);
    }


    ok(uniter({ walktree(mktree(3,'')) }) eq '000~001~010~011~100~101~110~111', 'gather example works');
}