The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Inline::SLang::Types - Support for S-Lang types in Perl

SYNOPSIS

  use Inline SLang => Config => BIND_SLFUNCS => [ "vmessage" ];
  use Inline SLang;
  use Math::Complex;

  # the S-Lang Complex_Type variable is automatically converted
  # to a Math::Complex object in Perl.
  #
  my $val = makecplx();
  print "Perl has been sent $val\n";

  # the multiplication is done using Math::Complex objects and
  # the result then converted to a S-Lang Complex_Type variable,
  # since vmessage is a S-Lang function [the %S means convert
  # the variable to its string representation].
  #
  vmessage( "S-Lang has been sent %S", $val * cplx(0,1) );

  my $type = typecplx($val);
  print "And the S-Lang datatype is $type\n";
  print "        Perl object        " .  $type->typeof . "\n";

  __END__
  __SLang__

  define makecplx() { return 3 + 4i; }
  define typecplx(cval) { return typeof(cval); }

The output of this code - which can be found in the source-code distribution as examples/types.pl - is:

  Perl has been sent 3+4i
  S-Lang has been sent (-4 + 3i)
  And the S-Lang datatype is Complex_Type
          Perl object        DataType_Type

DESCRIPTION

The aim of the type-handling in Inline::SLang is to allow a user to program "naturally" in Perl and S-Lang - i.e. to take advantage of the strengths of each language - and so native data types are used wherever possible. However, Perl objects (classes defined in this module) are used when necessary - for some poorly defined definition of necessary - to preserve type information.

As an example, consider swapping a complex number between S-Lang and Perl. In S-Lang it would be represented as a Complex_Type and in Perl we choose to use a Math::Complex object. Something simple - such as an array reference containing two elements - could have been used, but then we would not be able to convert it back into a Complex_Type variable in S-Lang (well, not without telling the computer this is what we wanted).

Version 0.20 of the module added support for the the Perl Data Language (ie PDL).

Supported S-Lang Data Types

The following S-Lang types may be returned from a S-Lang function to Perl. Note that the list does not include all synonyms for a type, although they are recognised; for instance the Int_Type is accepted but converted to Integer_Type.

See the "DATATYPE CLASSES" section below for further details.

  • NULL

    Converted to a Perl undef.

  • [Char|UChar|Short|UShort|Integer|UInteger|Long|ULong]_Type

    Converted to a Perl integer. The unsigned types are converted as unsigned values, whatever difference that may make.

  • [Float|Double]_Type

    Converted to a Perl floating-point number.

  • Complex_Type

    Converted to a Perl Math::Complex object.

  • String_Type

    Converted to a perl string.

  • Array_Type

    Converted to one of: a Perl array reference, a Perl Array_Type object, or a piddle.

  • Assoc_Type

    Converted to a Perl Assoc_Type object.

  • Struct_Type and "named" structures

    Struct_Type variables are converted to a Perl Struct_Type object, whilst "named" structures are converted to objects with the same name as the S-Lang struct name.

  • DataType_Type

    Converted to a Perl DataType_Type object.

  • Other S-Lang types are converted to a Perl class that matches the name of the S-Lang datatype. They are then treated in Perl as opaque objects, in that you can pass them back to S-Lang and let it access their contents but you can not do anything else with them in Perl.

Supported Perl Data Types

The following data types may be passed from Perl into S-Lang. Any other type results in the Perl interpreter issuing a croak; we could create an opaque datatype to store such values - much as we do when we come across a S-Lang datatype that we don't recognise - but this would only be useful if we also allow Perl to be embedded into S-Lang.

See the "DATATYPE CLASSES" section below for further details.

  • undef

    Converted to NULL (i.e. S-Lang's Null_Type datatype).

  • Integer

    Converted to S-Lang's Integer_Type.

  • Floating Point

    Converted to S-Lang's Double_Type.

  • Math::Complex

    Converted to S-Lang's Complex_Type.

  • String

    Converted to S-Lang's String_Type.

  • Array reference

    Converted to a S-Lang array with (hopefully) the correct datatype and dimensionality.

  • Perl Array_Type object

    Converted to a S-Lang array with datatype and dimensionality matching that of the Perl object.

  • Piddles

    Will be be converted to a S-Lang array with datatype and dimensionality matching that of the Perl object.

  • Hash reference

    Converted to S-Lang's Assoc_Type [Any_Type].

  • Perl Assoc_Type object.

    Converted to S-Lang's Assoc_Type with the datatype of the array being determined by the contents of the object.

  • Perl Struct_Type and derived objects.

    Converted to the matching S-Lang type (Struct_Type or the "named" struct).

  • Perl DataType_Type object.

    Converted to S-Lang's DataType_Type.

  • "Opaque" objects

    S-Lang data types that are handled as so-called "opaque" variables are converted back into the correct S-Lang variable type.

DATATYPE CLASSES

Objects are used to represent those S-Lang data types for which there is no corresponding Perl data type: for complex numbers we use the Math::Complex module which is distributed with Perl; arrays can be handled in a variety of ways - as a perl array reference, an Array_Type object, or a piddle (see the documentation for the Perl Data Language); and for other types we use a class specific to Inline::SLang.

  • Complex numbers

    Complex numbers are represented as Complex_Type in S-Lang and as a Math::Complex object in Perl. See the Math::Complex documentation for information on how to use this class.

  • Struct_Type and "named" structs

    S-Lang structures - variables with a type of Struct_Type - are represented using Struct_Type objects in Perl. Named structs - ie those created via a typedef struct {} XXX call - are represented using XXX objects in Perl; these objects are sub-classes of the Struct_Type class. The objects behave similarly to a hash reference, except that you can not add or delete keys, the order of the keys is fixed to match that of the structure, and there are a number of method calls that match the S-Lang language.

    See Inline::SLang::Struct for more information.

  • Associative arrays

    S-Lang associative arrays (Assoc_Type) are represented in Perl as Assoc_Type objects. These objects behave just as hash references do but have additional methods to match the S-Lang language.

    See Inline::SLang::Assoc for more information.

  • Arrays

    Support for S-Lang arrays (Array_Type) comes in three "flavours":

    1. As a Perl array reference.

    2. As a piddle (if you are using the Perl Data Language).

    3. As a Perl Array_Type object.

      It is expected that this object will rarely be used, at least directly.

    See Inline::SLang::Array for more information.

  • S-Lang data type.

    S-Lang Datatype_Type values are represented using Perl DataType_Type objects, which are described below.

  • Other types.

    A number of S-Lang types do not map to an obvious Perl type. For these types, Inline::SLang creates an object of class <type>, where <type> is the name of the S-lang datatype (i.e. the output of S-Lang's typeof function). Examples are the Ref_Type and Any_Type S-Lang variable types.

    The objects are treated as "opaque" containers; you can store them and send them back to S-Lang but there's essentially nothing else you can do with them directly in Perl.

    This currently includes the filehandle types File_Ptr_Type and File_FD_Type since it looks like the Perl I/O system is quite scary "under the hood" in v 5.8.0!

PERL OBJECTS

Each class provides a number of methods. These methods are not exported into the calling packages namespace, so they can only be accessed using the "object-oriented" form, i.e.

  $obj->foo()

Note that the new() method is not defined for some classes, which means you can only create them by calling a S-Lang function.

Common methods

All classes provide the following methods:

  • typeof()

    Returns a DataType_Type object which contains the the S-Lang datatype of the object. This object will return the name of the datatype when converted to a string.

  • stringify()

    The "print" method for the objects has been over-loaded to use the stringify() method: for most - probably all - types it will return the datatype name.

  • is_struct_type()

    Returns a 1 if the object represents a S-Lang structure - including "named" structures created via a typedef - and 0 otherwise.

Array_Type Objects

See Inline::SLang::Array.

Assoc_Type Objects

See Inline::SLang::Assoc.

Struct_Type Objects

See Inline::SLang::Struct.

DataType_Type Objects

Although you can use the new() constructor described below to create a DataType_Type variable, it is easier just to call the given type as a function. If you have specified !types as a value in the EXPORT configuration option (see Inline::SLang::Config for more details) then you can just say:

  my $var = Integer_Type();

otherwise you have to include the package name, as in the following

  my $var = Inline::SLang::Integer_Type();

Note that even though the functions take no arguments you have to supply the () in order for Perl to recognise it as a function. The return value ($var here) can be used just as the output of DataType_Type->new() can.

It is possible to use the names of type "synonyms" - such as Int_Type() and Float32_Type() - although the value they return is of the base type and not the synonym.

The class-specific methods are:

new()
  $dtype = DataType_Type->new([$type]);

The new() method accepts a string ($type) containing the name of the S-Lang datatype (e.g. "UChar_Type"). If no variable is supplied then "DataType_Type" is assumed. Synonyms of types (eg 'Int_Type' and 'Float32_Type') are accepted but automatically converted to the base type name. If you supply a name that does not map to a S-Lang datatype then the return value is undef.

In general you should probably be using the functional form described abode - i.e. use Integer_Type() - but this constructor can be useful when the data type is not known ahead of time.

stringify()

The name of the datatype represented by the object is returned.

For instance

  $type = DataType_Type->new("Any_Type");
  print("And the type is '$type'\n");

outputs

  And the type is 'Any_Type'.

The equality and inequality operators - namely ==, eq, ne, and != - have been over-ridden to work for variables containing DataType_Type objects. So you can say:

  my $val = some_function_call();
  print "Got a S-Lang array\n" if
    $val->typeof == Array_Type(); 

To see a list of all the possible datatypes recognised by a particular program use the INFO option provided by the Inline module, as described in the "What functions and namespaces have been bound to Perl?" section of Inline::SLang::Config.

Other objects - aka "opaque" variables

These objects are used to store S-Lang data types for which there is no obvious - or perhaps easy - way to represent in Perl. Examples are the Ref_Type and Any_Type S-Lang variable types.

The Perl objects can only be created from S-Lang (i.e. there are no new() methods). In fact, there is little that you can do with these objects in Perl; if you want to access/change the value referred to then you need to pass the object back to S-Lang.

There are no class-specific methods. This means that there is no way of creating one of these objects except from S-Lang (i.e. there is no object constructor in Perl).

An example using S-Lang references - available as examples/use_refs.pl in the source code - is:

  use Inline 'SLang';

  my $ref = getfoo();
  print "\$ref is a " . ref($ref) . " object\n";
  print "And when printed as a string = $ref\n";
  printfoo($ref);
  changefoo($ref,"no it isn't");
  printfoo($ref);

  __END__
  __SLang__

  variable foo = "this is a string";
  define getfoo() { return &foo; }
  define printfoo(x) { () = printf("foo = [%s]\n", @x ); }
  define changefoo(x,y) { @x = y; }

The output of this script is:

  $ref is a Ref_Type object
  And when printed as a string = Ref_Type
  foo = [this is a string]
  foo = [no it isn't]

Note that to change the value pointed to by the reference we had to send the variable back to S-Lang and do the processing there.

For Any_Type variables (this is also available as examples/use_anytype.pl):

  use Inline 'SLang';

  my $a0 = getfoo(0);
  my $a1 = getfoo(1);
  my $a2 = getfoo(2);
  print "\nIn Perl:\n";
  printf "typeof(foo[0]) = %s\n", $a0->typeof;
  printf "typeof(foo[1]) = %s\n", $a1->typeof;
  printf "typeof(foo[2]) = %s\n",
    defined($a2) ? $a2->typeof : "undef";

  __END__
  __SLang__

  variable foo = Any_Type [3];
  foo[0] = "a string";
  foo[1] = 23;

  define getfoo(x) { return foo[x]; }
  message( "In S-Lang:" );
  vmessage( "typeof(foo[0]) = %s", string(typeof(foo[0])) );
  vmessage( "typeof(foo[1]) = %s", string(typeof(foo[1])) );
  vmessage( "typeof(foo[2]) = %s", string(typeof(foo[2])) );

The output of this script is:

  In S-Lang:
  typeof(foo[0]) = Any_Type
  typeof(foo[1]) = Any_Type
  typeof(foo[2]) = Null_Type

  In Perl:
  typeof(foo[0]) = Any_Type
  typeof(foo[1]) = Any_Type
  typeof(foo[2]) = undef

Note that the Null_Type value (in S-Lang) has been converted into a Perl undef value.

SEE ALSO

Inline::SLang::Array, Inline::SLang::Assoc, Inline::SLang::Struct, Inline::SLang, Math::Complex, PDL, PDL::Intro