package Camila::Prototype;

use Data::Dumper;

=head1 Camila::Prototype

This module is used internally for Camila and should not be used other
way. This documentation is maintained for Camila maintainers

=cut

my %prototype = (
		);

=head2 Registering functions/operators

To register a function we need to know the return type, what and how
many arguments they receive and the function that should be called to
evaluate the operation.

Types are identified by their name, like the perl modules.

The register method receives:

=over 4

=item function name;

=item return type;

=item list of arguments types;

=item reference to the evaluation method;

=back

=cut

sub register {
  my ($function_name,
      $return_type,
      $argument_list,
      $function) = @_;

  push @{$prototype{$function_name}}, {
				       return => $return_type,
				       arglist => $argument_list,
				       function => $function,
				      };
}

sub definition {
  my ($function_name, $argument_list) = @_;
  if (exists($prototype{$function_name})) {
    my @possible_definitions = @{$prototype{$function_name}};
    my $def;
    for $def (@possible_definitions) {
      my @args = @{$def->{arglist}};
      my $arg;
      my $found = 1;
      my $i = 0;
      for $arg (@args) {
	$found = 0 if $arg ne $argument_list->[$i];
	$i++;
      }
      return $def if ($found);
    }
    return {
	    error => "Called '$function_name' with ".
	    prety_types(@$argument_list).
	    " but prototypes are only defined for ".
	    join(", ",map {prety_types(@{$_->{arglist}})} @possible_definitions).
	    "\n"
	   };
  } else {
    return +{
	     error => "Called function '$function_name' not defined\n"
	    }
  }
}

sub prety_types {
  return "(".join(",",@_).")";
}

sub show_table {
  print Dumper(\%prototype);
}

1;
