### ----------------------------------------------------
### -- _
### -- Licenses: Artistic-2.0
### -- Authors: Daniel Sockwell
### -- File: t/SelfRecursion/02-basic.rakutest
### ----------------------------------------------------
use Test;

unit sub MAIN(Bool :b(:$bench), :r(:$runs)=1000);


{ use _;
  sub countdown($seconds) { if $seconds ≥ 0 { "$seconds…", |(&_($seconds - 1)) }
                            else            { "BLASTOFF!" } }

  countdown(5).&is-deeply: <5… 4… 3… 2… 1… 0… BLASTOFF!>,
                           "Basic sub recurses";
}


{ use _ <&_>;
  proto count-up(|){{*}}
  multi count-up(Int)                            { "Ok, buster, you're in trouble now!" }
  multi count-up(Int $one-two-three where * ≤ 3) { $one-two-three, |&_($one-two-three + 1)  }

  (try count-up(1)).&is-deeply: (1, 2, 3, "Ok, buster, you're in trouble now!"),
                                           "Basic multi recurses";
}

{ use Self::Recursion;
  multi fib(0) { 0 }
  multi fib(1) { 1 }
  multi fib($n where * > 0) { &_($n-1) + &_($n-2) }

  throws-like {fib 4}, X::_::Unsupported;
}


if not $bench {skip "benchmark test (run it with -b)", 1}
else {
    use _;
    my @a;
    sub simple-fn($n) { @a.push($n);
                        &_($n - 1) if $n > 0 }

    my $start-time = now;
    simple-fn($runs);
    @a.elems.&is: $runs+1, "Deep regression is run the right number of times";
    (@a.head(3), @a.tail(3)).&is-deeply: (($runs, $runs-1, $runs-2).Seq, (2, 1, 0).Seq),
                                         "Deep regression returns correct results";
    diag "Ran $runs calls in &sprintf('%.3f', now - $start-time) seconds";
}

plan 4;


