NAME
Inline::SLang::Types - Support for S-Lang types in Perl
SYNOPSIS
use Inline SLang;
use Math::Complex;
# $val is a Math::Complex object after this call
my $val = makecplx();
print "Perl has been sent $val\n";
# note: the multiplication is done using Math::Complex
printcplx( $val * cplx(0,1) );
my $type = typecplx($val);
print "And the S-Lang datatype is $type\n";
print " Perl " . ref($type) . "\n";
__END__
__SLang__
define makecplx() { return 3 + 4i; }
define printcplx(cval) {
() = printf( "S-Lang has been sent %s\n", string(cval) );
}
define typecplx(cval) { return typeof(cval); }
DESCRIPTION
***
*** This is currently a pre alpha release.
*** Use at your own risk
***
The aim is to allow a user to program "naturally" in Perl and S-Lang, and so native data types are used wherever possible. However, objects are used when necessary (for some un-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).
An alternative is to use the Perl Data Language (ie PDL), since it provides variables ("piddles") which retain type information and are optimised for numeric work. Support for PDL is planned (once the initial kinks of the perl interface have been worked out) but currently not implemented (as of v0.05). Note that this will not remove the need for a number of object types, such as Inline::SLang::struct
.
Supported Perl Data Types
The following data types may be passed from Perl into S-Lang. Any other type results in a croak
.
undef
Converted to
NULL
.Integer
Converted to S-Lang
Integer_Type
.Floating Point
Converted to S-Lang
Double_Type
.Math::Complex
Converted to S-Lang
Complex_Type
.String
Converted to S-Lang
String_Type
.Array Reference
*** NOT YET SUPPORTED ***
I am thinking about returning an array of type
Any_Type
, since there's no guarantee that the perl array will be of one type, or form a regular nD array. However, this isn't going to be remotely useful.The first element of the perl array can be useful, but if it contains "1.0" is it an array of strings?
Hash Reference
*** NOT YET SUPPORTED ***
This should be converted to a S-Lang
Assoc_Type
object.Inline::SLang::XXX Objects
Converted to S-Lang
XXX
, whereXXX
is a valid S-Lang variable type.The
Struct_Type
code may leak memory.
Supported S-Lang Data Types
The following S-Lang types may be returned from a S-Lang function to Perl.
NULL
Converted to a perl undef.
[Char|UChar|Short|UShort|Int|UInt|Long|ULong]_Type
Converted to a perl integer. The unsigned types are converted as unsigned values, whatever difference that makes.
[Float|Double]_Type
Converted to a perl floating-point number.
Complex_Type
Converted to a
Math::Complex
object.String_Type
Converted to a perl string.
Array_Type
Converted to a perl array reference. Currently only 1 and 2 dimensional arrays of numeric (including complex numbers) and strings are handled.
Assoc_Type
*** Partially supported ***
A reference to a hash array is returned. However, this only works if the values stored in the array are of a type which we can convert into a 1D array. So, '
variable a = Assoc_Type [Int_Type];
' will be converted, but 'variable b = Assoc_Type [];
' will not, since we do not currently support 1D arrays ofAny_Type
objects (an implementation isue).Struct_Type and "named" structures
An
Inline::SLang::XXX
object - whereXXX
is the S-Lang type - is created.See the
Inline::SLang::Struct_Type
discussion below for further details.Other S-Lang type
An object of class
Inline::SLang::XXX
is returned, whereXXX
is the name of the S-Lang data type. See below for further details.
DATATYPE CLASSES
***
*** Comments would be welcome on the following approach
*** It could be less verbose (particularly the
*** Inline::SLang::*** class names), but I think the
*** current approach is somewhat logical/easy to follow
***
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; for numeric types we may use piddles (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.
Numeric types as piddles
***
*** Support for PDL is not yet available (v0.06)
***
The Perl Data Language (PDL) is a set of perl modules designed to provide fast, efficient, numeric capabilities in Perl (if you routinely deal with arrays of numbers in Perl you should have a look at PDL; see http://pdl.perl.org/).
Currently S-Lang arrays are converted to Perl array references (as discussed below). This is fine for strings (and is the obvious representation), and does allow easy access to the data. However, for numeric arrays it's not the most efficient and presents issues when converting Perl to S-Lang data [ie one would have to loop through the entire array to work out what S-Lang datatype and dimensionality/sizes to use]. Perhaps we should use a reference to a scalar as done in Astro::FITS::CFITSIO, but this approach has it's own issues (how do we find out the size of the array?).
It is likely that a routine will be used to define whether S-Lang numeric arrays should be turned into piddles or references to perl arrays (following the approach of the Astro::FITS::CFITSIO module). However, unlike the CFITSIO module, I am likely to convert to either a perl array reference or a piddle - ie no reference to a character array representing the data (ie force users to use piddles if they want efficiency).
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 Inline::SLang::<type>
, where <type>
is the name of the S-lang datatype (i.e. the output of S-Lang's typeof
function).
Each class provides a number of methods, as listed below. 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 string containing the name of the S-Lang datatype of the object (which corresponds to the name of the Perl class without the leading
Inline::SLang::
). - stringify()
-
The "print" method for the objects has been over-loaded to use the
stringify()
method: for most types it will return the datatype name (namely the output of thetypeof()
method), whereas for certain classes - such asInline::SLang::Struct_Type
- it will print out a formated representation of the data.The class descriptions below describe the output format if it does not match that of the
typeof()
method. - is_struct_type()
-
Returns a 1 if the object represents a S-Lang structure - including "named" structures created via a typedef - and 0 otherwise.
Struct_Type and "named" structs
S-Lang structures - variables with a type of Struct_Type
- are represented using Inline::SLang::Struct_Type
objects. Named structs - ie created via typedef struct {} XXX
- are represented using Inline::SLang::XXX
objects; these objects are sub-classes of the Inline::SLang::Struct_Type
class.
The methods are similar to the S-Lang versions, although struct_
has been removed from the names and the get and set functions allow multiple fields to be specified in a single call. Not all S-Lang functions are available, although the functionality of the missing functions should be possible with the current interface.
Missing are
set_struct_fields()
_push_struct_field_values()
Need to add
something like copy() or dup() with "field-slicing" a la
dup_struct() in CIAO's varmm module.
The class-specific methods are:
- is_struct_type()
-
This returns 1.
- new()
-
@fields = ( "foo", "bar", "baz" ); $s1 = Inline::SLang::Struct_Type->new(@fields); $s2 = Inline::SLang::Struct_Type->new(\@fields);
Create a S-Lang structure from Perl. The
new()
method accepts a list of field names using either an array reference or as an actual list. The order of the array determines the order of the fields in the structure.For "named" structures, the
new()
method does not accept a list of field names, since the fields is fixed for a given named struct.It is not possible to set the values of the fields with this method (at least not for now; perhaps we should allow a hash reference to be supplied but then how do we define the order of the fields?).
- get_field_names()
-
@names = $s1->get_field_names();
Returns, as an array, the names of the fields contained in the structure. Note that, unlike S-Lang's
get_struct_field_names()
, it does not return an array reference - get_field()
-
$val = $s1->get_field( "bar" ); @vals = $s1->get_field( "foo", "baz" );
Returns the value of the specified field(s). If given more than one field name then the values are returned as an array.
The routine dies if given a field name that does not exist in the structure.
- set_field()
-
$s1->set_field( "bar", 1 ); $s1->set_field( foo => 23, baz => "a string" );
Sets the supplied to the supplied values. The argument list is interpreted as pairs of "field name", "new value"; as shown above the
=>
separator can be used to improve the readability of your code.The routine dies if given a field name that does not exist in the structure.
- stringify()
-
The structure type and contents are output. The output is currently very crude, and only really works if the fields contain scalars.
@f = ( "one", "two", "three" ); $s = Inline::SLang::Struct_Type->new(@f); $s->set_field("one",1,"two",2,"three",3); print "$s\n";
outputs
Structure Type: Struct_Type one = 1 two = 2 three = 3
As a simple example of using S-Lang struct's:
use Inline SLang;
$a = ret1();
print "Class of \$a is " . ref($a) . "\n";
print "$a\n";
$b = ret2();
print "Class of \$b is " . ref($b) . "\n";
print "$b\n";
__END__
__SLang__
define ret1() {
variable a = struct { a, b };
a.a = 1; a.b = "foo"; return a;
}
typedef struct { a, b } SimpleStruct_Type;
define ret2() {
variable a = @SimpleStruct_Type;
a.a = 2; a.b = "bar"; return a;
}
The output of this code is:
Class of $a is Inline::SLang::Struct_Type
Structure Type: Struct_Type
a = 1
b = foo
Class of $b is Inline::SLang::SimpleStruct_Type
Structure Type: SimpleStruct_Type
a = 2
b = bar
DataType_Type
S-Lang Datatype_Type
values are represented using Inline::SLang::DataType_Type
objects.
The class-specific methods are:
- new()
-
$dtype = Inline::SLang::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' for 'Integer_Type') are accepted but converted to the 'original' type name.
Note that if you supply a name that does not map to a S-Lang datatype then:
undef
will be returnedSeveral lines of text will be printed to
STDERR
by the S-Lang library, looking something like:S-Lang Error: Undefined Name: ... is undefined S-Lang Error: Undefined Name: called from line 1, file: ***string*** S-Lang Error: Undefined Name: called from eval: ...
- stringify()
-
The name of the datatype represented by the object is returned.
For instance
$type = Inline::SLang::DataType_Type->new("Any_Type"); print("And the type is '$type'\n");
outputs
And the type is 'Any_Type'.
Note that the
typeof()
method returns the string "DataType_Type" and not the value of the variable.
Other Inline::SLang::XXX objects
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 Ref_Type
and Any_Type
S-Lang 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, 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 Inline::SLang::Ref_Type object
And when printed as a string = Ref_Type
foo = [this is a string]
foo = [no it isn't]
And for Any_Type
variables:
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, Math::Complex, PDL
AUTHOR, COPYRIGHT, LICENSE, and WARRANTY
See the Inline::SLang documentation.