Quick actions

cmd+k|ctrl+k

Navigation

Languages

Untitled

Snippet info

Language

Raku

Visibility

unlisted

Author

legacy-anonymous

Created

2026-07-02T09:17:26.543936Z

Updated

2026-07-02T09:17:26.543936Z

enum Event <Exit Enter Quit Last Last-Phaser>;

role SupplyInspector {
    method event(
        Event:D  :$event!,
        Str:D    :$spec!,
                 :$value, # only present in Enter
        Numeric  :$elapsed, # not present in Enter
        Exception :$exception, # only present in Quit
        Str      :$phaser-spec, # only present in Quit and Last-Phaser
        Bool     :$has-phaser, # only present in Quit, Last and Last-Phaser
    ) { ... }
}

class SupplyInspector::Print does SupplyInspector {
    method event(Event:D :$event!, Str:D :$spec!, :$value,
                 Numeric :$elapsed, Exception :$exception,
                 Str :$phaser-spec, Bool :$has-phaser) {
        my $ts   = (now - INIT now).round(0.001) ~ 's';
        my sub c(Int $c, Str $t) { "\e[{$c}m{$t}\e[0m" }
        my $tag = c(31 + $event, $event.uc);

        say qq:to/END/.indent(4);
			[$ts]{
				$has-phaser eqv False ?? c(35, " NO PHASER") !! ""
			} $tag {$spec}{ 
				$value // ""
			}{
				$elapsed ?? " ({$elapsed.round(0.001)}s)" !! ""
			}{
				$exception ?? "\n{c(38, "Exception")}:\n{$exception.gist.indent(4)}" !! ""
			}{
				$phaser-spec ?? " [phaser: $phaser-spec]" !! ""
			}
			END
    }
}

sub INSPECT-SUPPLY(SupplyInspector :$inspector = SupplyInspector::Print.new) {
    use nqp;
    my &OLD := nqp::getlexdyn('&*ADD-WHENEVER');

    my &NEW := sub (Supply $s, &block) {
        my $spec  = "{&block.file}:{&block.line}";
        my $q     = &block.phasers('QUIT')[0];
        my $qspec = $q.DEFINITE ?? "{$q.file}:{$q.line}" !! Str;
        my $has-q = $q.DEFINITE;

        my @lasts = &block.phasers('LAST').map: -> &l {
            ("{&l.file}:{&l.line}", &l)
        }

        OLD($s, -> $value {
            my $enter = now;

            $inspector.event(:event(Enter), :$spec, :$value);

            LEAVE $inspector.event(:event(Exit), :$spec,
                                 :elapsed(now - $enter));

            QUIT {
                default {
                    my $enter = now;
                    $q($_) if $has-q;

                    $inspector.event(
                        :event(Quit), :$spec,
                        :exception($_),
                        :phaser-spec($qspec),
                        :has-phaser($has-q),
                        :elapsed(now - $enter),
                    );
                }
            }

            &block($value);

            LAST {
                my $enter = now;
                for @lasts -> ($lspec, $lphaser) {
                    my $enter = now;
                    $lphaser();
                    $inspector.event(
                        :event(Last-Phaser), :$spec,
                        :phaser-spec($lspec),
                        :has-phaser(True),
                        :elapsed(now - $enter),
                    );
                }
                $inspector.event(
                    :event(Last), :$spec,
                    :elapsed(now - $enter),
                    :has-phaser(@lasts.so),
                );
            }
        });
    }

    nqp::bindlexdyn('&*ADD-WHENEVER', &NEW);
}

sub foo($n) { 
    supply { 
        INSPECT-SUPPLY; 
        whenever Promise.in(1) { whenever ^3 { "$n: $_".say; sleep .2; } } } 
    };
await supply { 
    INSPECT-SUPPLY;
    for ^3 -> $n { 
        whenever foo($n) { LAST { say "end" } } 
    }
} # suddenly multithreaded
INFO