I'm thinking XS thoughts because we're going to need a few external
things at SOME point.... It would be so nice if Perl 6's XS was part of
the language, rather than an external pre-processor.
Something like:
module somesuch;
use External (language=>"C");
sub chdir(string $path //= $ENV{HOME}) is external(returns=>'int');
Then you could extract the C source like so:
perl -MExternal -e 'extract "chdir"'
Which would generate something along the very vague lines of:
#include<parrot_external.h>
/* modulename.c */
void perlexternal_chdir(parrot_sv *path) {
char* param_path = parrot_sv_to_char_STAR(path);
int RETVAL = chdir(param_path);
parrot_stackpush(parrot_int_to_iv(RETVAL));
}
The more complex case:
module getpw;
use External(language=>"C",PREP=>q{
#include<pwd.h>
#include<sys/types.h>});
class uid_t := class real; # Proposed class alias syntax (see below)
class gid_t := class real;
class passwd {
my string $.pw_name; # Proposed pseudo-classes "string" and "real"
my string $.pw_passwd; # are required to determine how to convert
my int $.pw_uid; # the value to C
my int $.pw_gid;
my string $.pw_gecos;
my string $.pw_dir;
my string $.pw_shell;
method storage { # storage returns a string name of the C type
# or a listref to the field names if it's a
# struct. If it's a scalar type in C, then
# this class must contain a $.internal of the
# appropriate Perl pseudo-class type (string,
# int or real).
return
[qw{
pw_name pw_passwd pw_uid pw_gid
pw_gecos pw_dir pw_shell
}]
}
}
sub getpwuid(uid_t $uid //= $_) is external(returns=>'passwd');
So, to recap:
All types passed to an externally defined function must be classes which
have well defined type behavior.
A subroutine is declared external by using "is external" which takes
argument pairs as parameters.
One of external's parameters is "returns" which take a class name as its
parameter. The function will return an object of the given class.
Classes can be aliased using the C<:=> construct
The following pseudo-classes are defined, which force a parrot-internal
storage and define the mechanism by which the value is translated to
external representation (these are all scalar types):
int - signed integer value
real - floating point
string - A character string
utf8string - A string which is never converted to ASCII
bytes - A string which may contain binary data including nul
each of these will implicitly have a method called "storage" which
returns their class name, for consistency.
There are some limitations to this very abstract approach, but most of
those can be overcome by defining glue functions in External's "PREP"
value. For example, if your target language is C++, and the default way
of implementing "is rw" in C++ is to expect the target function to take
a reference, then you could define your own glue function:
module a;
use External (language=>'C++', PREP=>q{
int _b(int& c) { aab(&c) }
});
sub b(int $c is rw) is external(returns=>'int', call=>'_b');
This lets us do the quick-and-dirty conversion automatically and the
fine-grained things in the target language.
The big advantage to this mechanism is that it does not require a user
to know the internals of Perl or Parrot in order to create linkage to
external programs.
Thoughts?
--
Aaron Sherman X137
[EMAIL PROTECTED]
"We had some good machines, but they don't work no more."
-"Faded Flowers" / Shriekback