=head1 NAME

Inline::SLang::Details - How Inline::SLang works

=head1 DESCRIPTION

This document is intended to provide details of how
L<Inline::SLang|Inline::SLang> weaves its magic. 
It's probably going to be most use in cases when you 
find apparently bizarre behaviour and wonder if it is
a bug or a feature.

The implementation for Inline::SLang was initally
based on the code found in Neil Watkiss'
L<Inline::Python> and L<Inline::Ruby> modules.
However, all bugs are my own creation.

=head2 What happens when Perl starts?

If the Perl code has not been evaluated before - or if
it has been changed since the previous run - the 
L<Inline> code kicks in to evaluate the S-Lang code.
This involves:

=over 2

=item 1

The S-Lang interpreter is started and queried to find
out all functions that are defined in the namespaces
listed in the C<BIND_NS> configuration option. 
The user-supplied
S-Lang code is then evaluated and the same set of
namespaces are again queried for the names of defined functions.
We also pick up any new namespaces that may have been 
defined if the C<BIND_NS> option is set to C<All>.

The names of the new functions - i.e. those functions added by the
user-supplied S-Lang code which the S-Lang
function C<_apropos()> lists when the flag value is set to 3 - are
stored for later use.

Complications:

=over 2

=item *

The C<_inline> namespace is ignored since this is used by the
module and should be considered off-limits.

=item *

The list of functions in C<bind_slfuncs> is added to the list
of functions to bind. This list can include functions defined as
part of the S-Lang Run-Time Library.

=item *

The fact that the module allows users to change the name
that namespaces and (some) functions have when mapped to Perl.

=back

=item 2

The list of defined S-Lang data types is found. This
includes user-defined types added by any imported modules
and "named" structures created via a S-Lang C<typedef>
statement.

Utility functions are created in Perl in the 
C<Inline::SLang> package which are
wrappers around calls to the C<DataType_Type> constructor.
This allows users to say C<Inline::SLang::UShort_Type()>
rather than C<< DataType_Type->new("UShort_Type") >>.

For those types we do not recognise - essentially all
user-defined types - we create objects with names
equal to the S-Lang variable name. The objects have very
few methods, and are just a way of carrying around a
reference to the S-Lang variable within Perl. The
S-Lang variable is saved in an associative array within
the C<_inline> namespace, to ensure that it is not
destroyed, and this is used when the Perl variable is
sent to a S-Lang function.
The "native" S-Lang types included in this list are:
C<Any_Type>, C<Ref_Type>, C<BString_Type>, C<File_Type>,
and C<FD_Type>. It would be useful if we could handle
these directly, but it is not easy (for instance I believe
it would be hard to use the file handles with 
C<PerlIO> code since C<PerlIO> makes assumptions
about who has opened the file).

The conversion between S-Lang and PDL types - e.g.
what type of piddle should an C<Int_Type> array be
converted to - has only been tested on 32-bit machines.
It may well fail on 64 bit machines.

=item 3

The information - including the S-Lang source code - is
written to a configuration file by L<Inline>. The default location
for the file is within the F<_Inline/> directory, but this can
be changed, as discussed in the L<Inline documentation|Inline>.

=back

If the code has previously been run then this information can just
be read from the configuration file. The information - whether read
from file or calculated directly - is used to:

=over 2

=item *

Set up the bindings between Perl and S-Lang functions.

=item *

Set up the Perl classes to handle the various datatypes that
can not be processed natively within Perl.

=item *

Set up the functions and variables in the C<_inline> namespace
(these should B<never> be accessed by user code).

=back

Once the S-Lang code has been processed the Perl code is
run.

=head1 CALLING A S-LANG FUNCTION

For each S-Lang function we want to bind to Perl, a small
Perl subroutine is created which pushes the S-Lang function
name (including any necessary namespace) onto the start of the
stack and then calls the C<Inline::SLang::sl_call_function()>
subroutine (which is defined in F<Slang.xs> and should B<never> be
called directly).
By including the S-Lang function name on the stack we allow the
Perl and S-Lang names to be different, as required by the 
C<BIND_SLFUNCS> and C<BIND_NS> 
L<configuration options|Inline::SLang::Config>.

The C<sl_call_function()> routine performs 4 operations:

=over 2

=item 1

The S-Lang interpreter is checked to see if the routine
is defined (this step could be removed).

=item 2

The remaining items on the Perl stack (the arguments to the
function) are converted to S-Lang variables and pushed onto
the S-Lang stack. The conversion from Perl to S-Lang
types is done by the C<pl2sl()> routine which is
defined in F<pl2sl.c>.

=item 3

The S-Lang function is called. The S-Lang error hook is used to
catch any errors that the S-Lang interpreter may throw; these
are converted to Perl errors by calling the C<croak()>
function so that they can be trapped by Perl's C<eval()>
routine.

=item 4

The S-Lang stack is examined and any variables returned by
the function are popped off, converted to Perl variables, and
pushed onto the Perl stack. The order of the S-Lang stack is
reversed when creating the Perl stack so that the S-Lang
statement

  ( x, y ) = some_func();

can be converted to

  ( my $x, my $y ) = some_func();

The conversion from S-Lang to Perl
types is done by the C<sl2pl()> routine which is
defined in F<sl2pl.c>.

=back

The major part of the whole module is the conversion between Perl and S-Lang
variables, namely the C<pl2sl()> and C<sl2pl()> routines. The routines
are not pretty - they could be re-written to allow additional convertors
to be "plugged in" - but they seem to work.

=head1 NOTES

=head2 How to find out what S-Lang functions and datatypes are recognised

The C<info> option of L<Inline> can be used to find out what
functions and data types are bound to Perl. If the code is stored
in the file F<script.pl>, use

  perl -MInline=info script.pl

L<Further details|Inline::SLang::Config/"What functions and namespaces have been bound to Perl?">
are available in the L<Inline::SLang::Config documentation|Inline::SLang::Config>.

=head2 Execution of S-Lang code

The S-Lang code is executed I<before> any Perl code. This can be
seen in the following example (available as
F<examples/order.pl> in the source distribution):

 use Inline 'SLang' => 'message("This is S-Lang");';
 print "This is Perl\n";

When run, the script displays:

 This is S-Lang
 This is Perl

=head2 Exporting symbols

The system used to bind functions to Perl
- in particular to make the symbols available to Perl - is
a "simplified" version of the Exporter Perl module (since I
have been unable to successfully use Exporter directly).

=head1 SEE ALSO

L<Inline::SLang>, L<Inline>

