# -*- perl -*-
###############################################################
#
# MiniMemoize.pm
#
# Memoizing demonstration module
# Copyright 1999 M-J. Dominus (mjd-tpj-memoize@plover.com)
# For details and explanation, see
#         http://www.plover.com/~mjd/perl/MiniMemoize/
#
# For a full-strength memoization module, see
#         http://www.plover.com/~mjd/perl/Memoize/
#
###############################################################


package MiniMemoize;
use Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(memoize);

use strict;

my %memotable;

sub memoize {
  my $function = shift;
  my $caller = caller;
  my $funcname;
  if (ref $function eq '') { 
    # Convert to code reference
    $function = $caller . "::$function" unless $function =~ /::/;
    $funcname = $function;
    no strict 'refs';
    $function = \&$function;
  }

  my $wrapper = eval qq{sub { _check_cache("$function", \@_) }};
  $memotable{$function} =
    { original => $function,
      memoized => $wrapper,
      cache => { },
    };

  { no strict 'refs';
    *{$funcname} = $wrapper if defined $funcname;
  }
  1;
}


sub _check_cache {
  my $what_func = shift;
  unless (exists $memotable{$what_func}) {
    # This `should never happen'
    croak("Tried to check cache of non-memoized function `$what_func'; aborting");
  }

  my $cache         = $memotable{$what_func}{cache};
  my $argstr = join $;, @_;
  if (exists $cache->{$argstr}) { return $cache->{$argstr} }

  my $real_function = $memotable{$what_func}{original};
  $cache->{$argstr} = $real_function->(@_);
}

1;
