/
TypedArray.pm6
130 lines (122 loc) · 4.68 KB
/
TypedArray.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# this is actually part of the Array class
my role TypedArray[::TValue] does Positional[TValue] {
proto method new(|) {*}
multi method new(:$shape!) {
set-descriptor(nqp::if(
nqp::defined($shape),
set-shape(self,$shape),
nqp::if(
Metamodel::EnumHOW.ACCEPTS($shape.HOW),
set-shape(self,$shape.^elems),
nqp::create(self)
)
))
}
multi method new() {
set-descriptor(nqp::create(self))
}
multi method new(\values, :$shape!) {
set-descriptor(nqp::if(
nqp::defined($shape),
set-shape(self,$shape),
nqp::if(
Metamodel::EnumHOW.ACCEPTS($shape.HOW),
set-shape(self,$shape.^elems),
nqp::create(self)
)
)).STORE(values)
}
multi method new(\values) {
set-descriptor(nqp::create(self)).STORE(values)
}
multi method new(**@values is raw, :$shape!) {
set-descriptor(nqp::if(
nqp::defined($shape),
set-shape(self,$shape),
nqp::if(
Metamodel::EnumHOW.ACCEPTS($shape.HOW),
set-shape(self,$shape.^elems),
nqp::create(self)
)
)).STORE(@values)
}
multi method new(**@values is raw) {
set-descriptor(nqp::create(self)).STORE(@values)
}
sub set-descriptor(\list) is raw {
nqp::stmts(
nqp::bindattr(list,Array,'$!descriptor',
ContainerDescriptor.new(:of(TValue), :default(TValue))
),
list
)
}
# must have a proto here to hide the candidates in Array
# otherwise we could bind any value to the Array
proto method BIND-POS(|) {*}
# these BIND-POSses are identical to Array's, except for bindval
multi method BIND-POS(Array:D: int $pos, TValue \bindval) is raw {
nqp::if(
nqp::islt_i($pos,0),
Failure.new(X::OutOfRange.new(
:what($*INDEX // 'Index'),:got($pos),:range<0..^Inf>)),
nqp::stmts(
nqp::if(
nqp::isconcrete(nqp::getattr(self,List,'$!reified')),
nqp::if(
nqp::isge_i(
$pos,nqp::elems(nqp::getattr(self,List,'$!reified'))
) && nqp::isconcrete(nqp::getattr(self,List,'$!todo')),
nqp::getattr(self,List,'$!todo').reify-at-least(
nqp::add_i($pos,1)),
),
nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer))
),
nqp::bindpos(nqp::getattr(self,List,'$!reified'),$pos,bindval)
)
)
}
# because this is a very hot path, we copied the code from the int candidate
multi method BIND-POS(Array:D: Int:D $pos, TValue \bindval) is raw {
nqp::if(
nqp::islt_i($pos,0),
Failure.new(X::OutOfRange.new(
:what($*INDEX // 'Index'),:got($pos),:range<0..^Inf>)),
nqp::stmts(
nqp::if(
nqp::isconcrete(nqp::getattr(self,List,'$!reified')),
nqp::if(
nqp::isge_i(
$pos,nqp::elems(nqp::getattr(self,List,'$!reified'))
) && nqp::isconcrete(nqp::getattr(self,List,'$!todo')),
nqp::getattr(self,List,'$!todo').reify-at-least(
nqp::add_i($pos,1)),
),
nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer))
),
nqp::bindpos(nqp::getattr(self,List,'$!reified'),$pos,bindval)
)
)
}
multi method perl(::?CLASS:D \SELF:) {
my $args = self.map({ ($_ // TValue).perl(:arglist) }).join(', ');
'Array[' ~ TValue.perl ~ '].new(' ~ $args ~ ')';
}
}
method ^parameterize(Mu:U \arr, Mu \t, |c) {
if nqp::isconcrete(t) {
"Can not parameterize {arr.^name} with {t.perl}"
}
elsif c.elems == 0 {
my $what := arr.^mixin(TypedArray[t]);
# needs to be done in COMPOSE phaser when that works
$what.^set_name("{arr.^name}[{t.^name}]");
$what
}
else {
"Can only type-constrain Array with a single [ValueType]"
}
}
}
#========== closed down the Array class started in src/core.c/Array.pm6 =======
# vim: ft=perl6 expandtab sw=4