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

Reply via email to