-
-
Notifications
You must be signed in to change notification settings - Fork 372
/
Typed.pm6
111 lines (104 loc) · 3.54 KB
/
Typed.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
my role Array::Typed[::TValue] does Positional[TValue] {
proto method new(|) {*}
multi method new(:$shape!) {
set-descriptor(
nqp::defined($shape)
?? self.set-shape($shape)
!! Metamodel::EnumHOW.ACCEPTS($shape.HOW)
?? self.set-shape($shape.^elems)
!! nqp::create(self)
)
}
multi method new() {
set-descriptor(nqp::create(self))
}
multi method new(\values, :$shape!) {
set-descriptor(
nqp::defined($shape)
?? self.set-shape($shape)
!! Metamodel::EnumHOW.ACCEPTS($shape.HOW)
?? self.set-shape($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::defined($shape)
?? self.set-shape($shape)
!! Metamodel::EnumHOW.ACCEPTS($shape.HOW)
?? self.set-shape($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::bindattr(list,Array,'$!descriptor',
ContainerDescriptor.new(:of(TValue), :default(TValue))
);
list
}
method !out-of-range(int $got) {
Failure.new(
X::OutOfRange.new(:what($*INDEX // 'Index'),:$got,:range<0..^Inf>)
)
}
# 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: uint $pos, TValue \bindval) is raw {
nqp::if(
nqp::isconcrete(
my $reified := nqp::getattr(self,List,'$!reified')
),
nqp::if(
nqp::isge_i($pos,nqp::elems($reified))
&& nqp::isconcrete(nqp::getattr(self,List,'$!todo')),
nqp::getattr(self,List,'$!todo').reify-at-least(
nqp::add_i($pos,1)),
),
($reified := nqp::bindattr(
self,List,'$!reified',nqp::create(IterationBuffer)
))
);
nqp::bindpos($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),
self!out-of-range($pos),
nqp::stmts(
nqp::if(
nqp::isconcrete(
my $reified := nqp::getattr(self,List,'$!reified')
),
nqp::if(
nqp::isge_i($pos,nqp::elems($reified))
&& nqp::isconcrete(nqp::getattr(self,List,'$!todo')),
nqp::getattr(self,List,'$!todo').reify-at-least(
nqp::add_i($pos,1)
)
),
($reified := nqp::bindattr(
self,List,'$!reified',nqp::create(IterationBuffer)
))
),
nqp::bindpos($reified,$pos,bindval)
)
)
}
multi method raku(::?CLASS:D:) {
my $type := nqp::getattr(self,Array,'$!descriptor').of.^name;
my $raku := self.map({
nqp::isconcrete($_) ?? .raku(:arglist) !! $type
}).join(', ');
'Array[' ~ $type ~ '].new(' ~ $raku ~ ')'
}
}
# vim: expandtab shiftwidth=4