Hello,
I was trying to write a NativeCall interface to a C library, but I stumbled
upon a problem (
https://stackoverflow.com/questions/44266457/array-of-structs-as-an-attribute-of-a-perl-6-nativecall-struct
).
The best way to solve that problem would be to add a new keyword to the
NativeCall module, which I think is quite hard, so I'm trying a less fancy
alternative.
The problem itself looks like this: I have a class with a bunch of elements
which I would like to access as an array (I can't use a Perl6 Array in a
NativeCall class).
Reducing the problem to the bare bones, my class looks like
Class A {
has $.a0 is rw;
has $.a1 is rw;
has $.a2 is rw;
has $.a3 is rw;
has $.a4 is rw;
}
My first attempt was to use meta methods to access the attributes:
class A does Positional {
has $.a0 is rw;
has $.a1 is rw;
has $.a2 is rw;
has $.a3 is rw;
has $.a4 is rw;
method AT-POS($index) is rw {
my $a = A.^attributes(:local)[$index];
$a.get_value(self);
}
}
This works if I just need to read the values, but if I needed to write them
I should use the set_value metamethod:
$a.set_value(self, $value);
The detail I miss is: how do I know whether the AT-POS method has been
called to produce an rvalue or an lvalue?
The second attempt was to use a Proxy object:
class A does Positional {
has $.a0 is rw;
has $.a1 is rw;
has $.a2 is rw;
has $.a3 is rw;
has $.a4 is rw;
method AT-POS(::?CLASS:D: $index) is rw {
my $a = A.^attributes(:local)[$index];
Proxy.new(
FETCH => method () { $a.get_value(self) },
STORE => method ($value) { $a.set_value(self, $value) }
);
}
}
sub MAIN
{
my A $a .= new;
$a.a0 = 0;
$a.a1 = 1;
say $a[0];
say $a[1];
say $a[2];
$a[0] = 42;
say $a[0];
}
But this program just hangs.
When run in the debugger I get this:
>>> LOADING Proxy.p6
+ Exception Thrown
| Died
+ Proxy.p6 (25 - 29)
| }
|
| sub MAIN
| {
| my A $a .= new;
I'm clueless here.
What am I doing wrong?
Can anyone help?
Thank you!
--
Fernando Santagata