package Language::Lisp::ECLs;

use 5.008;
use strict;

our $VERSION = '0.21';

require XSLoader;
XSLoader::load('Language::Lisp::ECLs', $VERSION);

sub new {
    cl_boot();
    return bless {}, __PACKAGE__;
}

sub eval_string {
    my $self = shift;
    return _eval_string(@_);
}
sub eval {
    my $self = shift;
    return _eval(@_);
}

sub stringify {
    my $self = shift;
    return "{dummied stringification}";
}

package Language::Lisp::ECLs::Symbol;
our @ISA = ('Language::Lisp::ECLs');
package Language::Lisp::ECLs::Package;
our @ISA = ('Language::Lisp::ECLs');
package Language::Lisp::ECLs::String;
our @ISA = ('Language::Lisp::ECLs');
package Language::Lisp::ECLs::Code;
our @ISA = ('Language::Lisp::ECLs');
package Language::Lisp::ECLs::Generic;
our @ISA = ('Language::Lisp::ECLs');

1;

__END__

=head1 NAME

Language::Lisp::ECLs - Perl extension for ECL lisp

=head1 SYNOPSIS

  use Language::Lisp::ECLs;
  my $cl = new Language::Lisp::ECLs;
  my $r = $cl->eval_string("(format nil \"[~S]\" 'qwerty)");
  my $lam = $cl->eval_string("(lambda (x y) (+ x y))");
  $lam->funcall(5,9); # results 14

=head1 DESCRIPTION

Language::Lisp::ECLs is a bit easier to use than Language::Lisp because of
embeddable nature of ECLs. Language::Lisp uses different approach because
they are other way down: Lisp calls Perl and not vice versa.

=head2 new()

The C<new> method used to create C<Language::Lisp::ECLs> object which is
used to talk with underlying lisp. This object looks like an interpreter
instance, although there is actually no interpreter instance created.
Instead, this object is used to create a handy way of invoking API: given that
you have C<$cl> object you can execute:

  my $res = $cl->eval_string("(format nil \"~A\" (expt 2 1000))");

which is equivalent to

  my $res = Language::Lisp::ECLs::eval_string(undef, "....");

but is much better to use.

=head2 Passing parameters to ECL and getting results from ECL

Required Perl objects converted to Lisp objects and vice versa.
Compatible types are converted as-is (e.g. ECL type t_integer becomes
SvIV), all other types are blessed into some package, for example into
C<Language::Lisp::ECLs::Symbol>

This is done behind the scenes and user should not bother about this.

This makes following code to work:

  my $lam = $cl->eval_string("(lambda (x y) (+ x y))");
  print $lam->funcall(40,2);     # prints 42
  print $cl->funcall($lam,40,2); # ... another way to say the same

=head2 $cl->eval_string(string)

runs string within ECLs interpreter and returns whatever lisp returns to us.
Internally this transforms to the call C<si_safe_eval(...);>

=head2 $cl->eval(lisp_object)

same as eval_string but takes lisp object instead of string as argument.

=head2 $lispobj->funcall(...)

given lisp object blessed to package Language::Lisp::ECLs::Code calls the
procedure.

=head2 EXPORT

None. No namespace pollution, the greens are happy.

=head1 BUGS

=over

=item *

ECL uses Boehm GC, and at the moment of writing it did not had reliable
interface on returning memory to GC, so the leaks of memory are unavoidable.

=item *

C<funcall> can not take more than 10 args - this should be fixed.

=back

=head1 SEE ALSO

Language::Lisp

=head1 AUTHOR

Vadim Konovalov, E<lt>vkon@cpan.orgE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2008 by VKON

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.004 or,
at your option, any later version of Perl 5 you may have available.


=cut

