forked from cxreg/zavolaj
/
NativeCall.pm6
112 lines (103 loc) · 3.11 KB
/
NativeCall.pm6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
class OpaquePointer { }
class NativeArray {
has $!unmanaged;
has $!of;
has $!max-index = -1;
method postcircumfix:<[ ]>($idx) {
if $idx > $!max-index {
self!update-desc-to-index($idx);
}
Q:PIR {
$P0 = find_lex 'self'
$P0 = getattribute $P0, '$!unmanaged'
$P1 = find_lex '$idx'
$S0 = $P0[$P1]
%r = box $S0
};
}
method !update-desc-to-index($idx) {
my $fpa = pir::new__Ps('ResizableIntegerArray');
my $typeid;
given $!of {
when Str { $typeid = -70 }
when Int { $typeid = -92 }
when Num { $typeid = -83 }
default { die "Unknown type"; }
}
Q:PIR {
$P0 = find_lex '$fpa'
$P1 = find_lex '$typeid'
$P2 = find_lex '$idx'
$I0 = $P2
inc $I0
$I1 = 0
$I2 = $P1
loop:
if $I1 > $I0 goto loop_end
push $P0, $I2
push $P0, 1
push $P0, 0
inc $I1
goto loop
loop_end:
};
pir::assign__vPP(pir::descalarref__PP($!unmanaged), $fpa);
}
method Bool() {
Q:PIR {
$P0 = find_lex 'self'
$P0 = getattribute $P0, '$!unmanaged' # a Parrot UnManagedStruct
$I0 = defined $P0
%r = box $I0
} ?? Bool::True !! Bool::False;
}
}
our sub map-type-to-sig-char(Mu $type) {
given $type {
when Int { 'i' }
when Str { 't' }
when Num { 'd' }
when Rat { 'd' }
when OpaquePointer { 'p' }
when Positional { 'p' }
default { die "Can not handle type " ~ $_.perl ~ " in an 'is native' signature." }
}
}
our sub perl6-sig-to-backend-sig(Routine $r) {
my $sig-string = $r.returns === Mu ?? 'v' !! map-type-to-sig-char($r.returns());
my @params = $r.signature.params();
for @params -> $p {
$sig-string = $sig-string ~ map-type-to-sig-char($p.type);
}
return $sig-string;
}
our sub make-mapper(Mu $type) {
given $type {
when Positional {
-> \$unmanaged-struct {
NativeArray.new(unmanaged => $unmanaged-struct, of => $type.of)
}
}
default { -> \$x { $x } }
}
}
our multi trait_mod:<is>(Routine $r, $libname, :$native!) {
my $entry-point = $r.name();
my $call-sig = perl6-sig-to-backend-sig($r);
my $return-mapper = make-mapper($r.returns);
my $lib = pir::loadlib__Ps($libname);
# warn "routine $r.name() signature $call-sig";
unless $lib {
die "The native library '$libname' required for '$entry-point' could not be located";
}
pir::setattribute__vPsP($r, '$!do', pir::clone__PP(-> |$c {
$return-mapper(
(pir::dlfunc__PPss(
pir::descalarref__PP($lib),
$entry-point,
$call-sig
) // die("Could not locate symbol '$entry-point' in native library '$libname'")
).(|$c)
)
}));
}