#!/usr/bin/env perl

# Copyright (c) 2015 Christian Jaeger, copying@christianjaeger.ch
# This is free software. See the file COPYING.md that came bundled
# with this file.

use strict; use warnings; use warnings FATAL => 'uninitialized';

use Scalar::Util "weaken";
use BSD::Resource;

sub rss () {
    (BSD::Resource::getrusage(BSD::Resource::RUSAGE_SELF()))[2]
}

sub naturals {
    my $f; $f= sub {
	my ($n)= @_;
	my $f=$f;
	sub {
	    if ($n > 0) {
		[ $n, &$f($n - 1) ]
	    } else {
		undef
	    }
	}
    };
    my $f_= $f; weaken $f;
    goto &$f_;
}

sub stream_sum {
    my ($s)=@_;
    #weaken $_[0];
    # ^ not necessary here, since, unlike with FP::Lazy::Promise,
    # resulting value is not saved in its 'generating container'
    my $tot=0;
  LP: {
      if (my $fs= &$s) {
	  ($tot, $s)= ($$fs[0] + $tot, $$fs[1]);
	  goto LP;
      } else {
	  $tot
      }
    }
}

@ARGV==2 or die "usage: $0 n N";
my ($n,$N)= @ARGV;

my $start= rss;

my $res;
for (1..$N) {
    my $ns= naturals $n;
    $res= stream_sum $ns;
}

print $res,"\n";

my $end= rss;

if (($end - $start) / $start > 1.5) {
    die "leaked: $start .. $end";
}

