1. # this is actually part of the Array class
  2. my role Shaped1Array does ShapedArray {
  3. multi method AT-POS(::?CLASS:D: int \one) is raw {
  4. nqp::ifnull(
  5. nqp::atpos(
  6. nqp::getattr(self,List,'$!reified'),
  7. one),
  8. AT-POS-CONTAINER(self,one)
  9. )
  10. }
  11. multi method AT-POS(::?CLASS:D: Int:D \one) is raw {
  12. nqp::ifnull(
  13. nqp::atpos(
  14. nqp::getattr(self,List,'$!reified'),
  15. one),
  16. AT-POS-CONTAINER(self,one)
  17. )
  18. }
  19. sub AT-POS-CONTAINER(\array, int \one) is raw {
  20. nqp::p6bindattrinvres(
  21. (my $scalar := nqp::p6scalarfromdesc(
  22. nqp::getattr(array,Array,'$!descriptor'))),
  23. Scalar,
  24. '$!whence',
  25. -> { nqp::bindpos(
  26. nqp::getattr(array,List,'$!reified'),
  27. one, $scalar) }
  28. )
  29. }
  30. multi method ASSIGN-POS(::?CLASS:D: int \one, \value) {
  31. nqp::ifnull(
  32. nqp::atpos(
  33. nqp::getattr(self,List,'$!reified'),
  34. one),
  35. nqp::bindpos(
  36. nqp::getattr(self,List,'$!reified'),
  37. one,
  38. nqp::p6scalarfromdesc(nqp::getattr(self,Array,'$!descriptor')))
  39. ) = value
  40. }
  41. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, \value) {
  42. nqp::ifnull(
  43. nqp::atpos(
  44. nqp::getattr(self,List,'$!reified'),
  45. one),
  46. nqp::bindpos(
  47. nqp::getattr(self,List,'$!reified'),
  48. one,
  49. nqp::p6scalarfromdesc(nqp::getattr(self,Array,'$!descriptor')))
  50. ) = value
  51. }
  52. multi method EXISTS-POS(::?CLASS:D: int \one) {
  53. nqp::p6bool(
  54. nqp::islt_i(one,nqp::elems(nqp::getattr(self,List,'$!reified')))
  55. && nqp::not_i(nqp::isnull(
  56. nqp::atpos(nqp::getattr(self,List,'$!reified'),one)
  57. ))
  58. )
  59. }
  60. multi method EXISTS-POS(::?CLASS:D: Int:D \one) {
  61. nqp::p6bool(
  62. nqp::islt_i(one,nqp::elems(nqp::getattr(self,List,'$!reified')))
  63. && nqp::not_i(nqp::isnull(
  64. nqp::atpos(nqp::getattr(self,List,'$!reified'),one)
  65. ))
  66. )
  67. }
  68. multi method DELETE-POS(::?CLASS:D: int \one) is raw {
  69. nqp::if(
  70. nqp::isnull(my $value := nqp::atpos(
  71. nqp::getattr(self,List,'$!reified'),
  72. one)),
  73. Nil,
  74. nqp::stmts(
  75. nqp::bindpos(
  76. nqp::getattr(self,List,'$!reified'),
  77. one, nqp::null),
  78. $value
  79. )
  80. )
  81. }
  82. multi method DELETE-POS(::?CLASS:D: Int:D \one) is raw {
  83. nqp::if(
  84. nqp::isnull(my $value := nqp::atpos(
  85. nqp::getattr(self,List,'$!reified'),
  86. one)),
  87. Nil,
  88. nqp::stmts(
  89. nqp::bindpos(
  90. nqp::getattr(self,List,'$!reified'),
  91. one, nqp::null),
  92. $value
  93. )
  94. )
  95. }
  96. multi method BIND-POS(::?CLASS:D: int \one, \value) {
  97. nqp::bindpos(
  98. nqp::getattr(self,List,'$!reified'),
  99. one, value
  100. )
  101. }
  102. multi method BIND-POS(::?CLASS:D: Int:D \one, \value) {
  103. nqp::bindpos(
  104. nqp::getattr(self,List,'$!reified'),
  105. one, value
  106. )
  107. }
  108. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  109. nqp::stmts(
  110. (my $to := nqp::getattr(self,List,'$!reified')),
  111. (my $from := nqp::getattr(from,List,'$!reified')),
  112. nqp::if(
  113. nqp::iseq_i(
  114. (my int $elems = nqp::elems($to)),nqp::elems($from)),
  115. nqp::stmts(
  116. (my $desc := nqp::getattr(self,Array,'$!descriptor')),
  117. (my int $i = -1),
  118. nqp::while(
  119. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  120. # always create a new container in case the from list
  121. # contains containers already existing in the to list
  122. # e.g. after having done a .reverse or .rotate
  123. nqp::bindpos($to,$i,nqp::p6scalarfromdesc($desc)) =
  124. nqp::atpos($from,$i)
  125. ),
  126. self
  127. ),
  128. X::Assignment::ArrayShapeMismatch.new(
  129. source-shape => from.shape,
  130. target-shape => self.shape
  131. ).throw
  132. )
  133. )
  134. }
  135. multi method STORE(::?CLASS:D: Iterable:D \in) {
  136. nqp::stmts(
  137. (my \list := nqp::getattr(self,List,'$!reified')),
  138. (my \desc := nqp::getattr(self,Array,'$!descriptor')),
  139. (my \iter := in.iterator),
  140. (my int $elems = nqp::elems(list)),
  141. (my int $i = -1),
  142. nqp::until(
  143. nqp::eqaddr((my $pulled := iter.pull-one),IterationEnd)
  144. || nqp::iseq_i(($i = nqp::add_i($i,1)),$elems),
  145. nqp::ifnull(
  146. nqp::atpos(list,$i),
  147. nqp::bindpos(list,$i,nqp::p6scalarfromdesc(desc))
  148. ) = $pulled
  149. ),
  150. nqp::unless(
  151. nqp::islt_i($i,$elems) || iter.is-lazy,
  152. nqp::atpos(list,$i) # too many values on non-lazy iter, error
  153. ),
  154. self
  155. )
  156. }
  157. multi method STORE(::?CLASS:D: Mu \item) {
  158. nqp::stmts(
  159. (nqp::ifnull(
  160. nqp::atpos(nqp::getattr(self,List,'$!reified'),0),
  161. nqp::bindpos(nqp::getattr(self,List,'$!reified'),0,
  162. nqp::p6scalarfromdesc(
  163. nqp::getattr(self,Array,'$!descriptor')))
  164. ) = item),
  165. self
  166. )
  167. }
  168. multi method keys(::?CLASS:D:) {
  169. Seq.new(Rakudo::Iterator.IntRange(0,self.shape.AT-POS(0) - 1))
  170. }
  171. multi method kv(::?CLASS:D:) {
  172. Seq.new(Rakudo::Iterator.KeyValue(self.iterator))
  173. }
  174. multi method pairs(::?CLASS:D:) {
  175. Seq.new(Rakudo::Iterator.Pair(self.iterator))
  176. }
  177. multi method antipairs(::?CLASS:D:) {
  178. Seq.new(Rakudo::Iterator.AntiPair(self.iterator))
  179. }
  180. method iterator(::?CLASS:D:) {
  181. class :: does Iterator {
  182. has Mu $!reified;
  183. has Mu $!desc;
  184. has int $!pos;
  185. method !SET-SELF(Mu \list) {
  186. nqp::stmts(
  187. ($!reified := nqp::getattr(list,List,'$!reified')),
  188. ($!desc := nqp::getattr(list,Array,'$!descriptor')),
  189. ($!pos = -1),
  190. self
  191. )
  192. }
  193. method new(Mu \list) { nqp::create(self)!SET-SELF(list) }
  194. method pull-one() is raw {
  195. nqp::if(
  196. nqp::islt_i(
  197. ($!pos = nqp::add_i($!pos,1)),
  198. nqp::elems($!reified)
  199. ),
  200. nqp::ifnull(
  201. nqp::atpos($!reified,$!pos),
  202. nqp::p6bindattrinvres(
  203. (my $scalar := nqp::p6scalarfromdesc($!desc)),
  204. Scalar,
  205. '$!whence',
  206. -> { nqp::bindpos($!reified,$!pos,$scalar) }
  207. )
  208. ),
  209. IterationEnd
  210. )
  211. }
  212. method push-all($target --> IterationEnd) {
  213. nqp::stmts(
  214. (my int $elems = nqp::elems($!reified)),
  215. (my int $i = $!pos),
  216. nqp::while(
  217. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  218. $target.push(
  219. nqp::ifnull(
  220. nqp::atpos($!reified,$i),
  221. nqp::p6bindattrinvres(
  222. (my $scalar := nqp::p6scalarfromdesc($!desc)),
  223. Scalar,
  224. '$!whence',
  225. -> { nqp::bindpos($!reified,$i,$scalar) }
  226. )
  227. )
  228. )
  229. ),
  230. ($!pos = $i) # mark as done
  231. )
  232. }
  233. method count-only() { nqp::p6box_i(nqp::elems($!reified)) }
  234. method bool-only() { nqp::p6bool(nqp::elems($!reified)) }
  235. method sink-all(--> IterationEnd) {
  236. $!pos = nqp::elems($!reified)
  237. }
  238. }.new(self)
  239. }
  240. method reverse(::?CLASS:D:) is nodal {
  241. Seq.new(nqp::if(
  242. (my int $elems = nqp::elems(
  243. my $from := nqp::getattr(self,List,'$!reified')
  244. )),
  245. nqp::stmts(
  246. (my int $last = nqp::sub_i($elems,1)),
  247. (my int $i = -1),
  248. (my $to := nqp::setelems(nqp::create(IterationBuffer),$elems)),
  249. nqp::while(
  250. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  251. nqp::bindpos($to,nqp::sub_i($last,$i),
  252. nqp::decont(nqp::atpos($from,$i)))
  253. ),
  254. Rakudo::Iterator.ReifiedList($to)
  255. ),
  256. Rakudo::Iterator.Empty
  257. ))
  258. }
  259. method rotate(::?CLASS:D: Int(Cool) $rotate = 1) is nodal {
  260. Rakudo::Internals.RotateListToList(
  261. self, $rotate, self.new(:shape(self.shape)))
  262. }
  263. method sum() is nodal { self.List::sum }
  264. }