1. # for our tantrums
  2. my class X::TypeCheck { ... };
  3. my class X::TypeCheck::Splice { ... }
  4. my class X::Subscript::Negative { ... };
  5. my class X::NotEnoughDimensions { ... };
  6. my class X::Assignment::ArrayShapeMismatch { ... };
  7. # stub what we need now
  8. my class array is repr('VMArray') { ... };
  9. # An Array is a List that ensures every item added to it is in a Scalar
  10. # container. It also supports push, pop, shift, unshift, splice, BIND-POS,
  11. # and so forth.
  12. my class Array { # declared in BOOTSTRAP
  13. # class Array is List
  14. # has Mu $!descriptor;
  15. my class ArrayReificationTarget {
  16. has $!target;
  17. has $!descriptor;
  18. method new(\target, Mu \descriptor) {
  19. nqp::stmts(
  20. nqp::bindattr((my \rt = nqp::create(self)),
  21. self,'$!target',target),
  22. nqp::p6bindattrinvres(rt,
  23. self,'$!descriptor',descriptor)
  24. )
  25. }
  26. method push(Mu \value) {
  27. nqp::push($!target,
  28. nqp::assign(nqp::p6scalarfromdesc($!descriptor), value));
  29. }
  30. method append(IterationBuffer:D $buffer) {
  31. nqp::if(
  32. (my int $elems = nqp::elems($buffer)),
  33. nqp::stmts(
  34. (my int $i = -1),
  35. nqp::while(
  36. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  37. nqp::push($!target,nqp::assign(
  38. nqp::p6scalarfromdesc($!descriptor),
  39. nqp::atpos($buffer,$i)
  40. ))
  41. )
  42. )
  43. )
  44. }
  45. }
  46. my class ListReificationTarget {
  47. has $!target;
  48. method new(\target) {
  49. nqp::p6bindattrinvres(nqp::create(self), self, '$!target', target);
  50. }
  51. method push(Mu \value) {
  52. nqp::push($!target,
  53. nqp::decont(value));
  54. }
  55. method append(IterationBuffer:D \buffer) {
  56. nqp::splice($!target,buffer,nqp::elems($!target),0)
  57. }
  58. }
  59. multi method clone(Array:D:) {
  60. nqp::stmts(
  61. (my \iter := self.iterator),
  62. (my \result := nqp::p6bindattrinvres(nqp::create(self),
  63. Array, '$!descriptor', nqp::isnull($!descriptor) ?? (nqp::null) !! nqp::clone($!descriptor))),
  64. nqp::if(
  65. nqp::eqaddr(
  66. IterationEnd,
  67. iter.push-until-lazy:
  68. my \target := ArrayReificationTarget.new(
  69. (my \buffer := nqp::create(IterationBuffer)),
  70. nqp::isnull($!descriptor) ?? (nqp::null) !! nqp::clone($!descriptor))),
  71. nqp::p6bindattrinvres(result, List, '$!reified', buffer),
  72. nqp::stmts(
  73. nqp::bindattr(result, List, '$!reified', buffer),
  74. nqp::bindattr((my \todo := nqp::create(List::Reifier)),
  75. List::Reifier,'$!current-iter', iter),
  76. nqp::bindattr(todo,
  77. List::Reifier,'$!reified', buffer),
  78. nqp::bindattr(todo,
  79. List::Reifier,'$!reification-target', target),
  80. nqp::p6bindattrinvres(result, List, '$!todo', todo))))
  81. }
  82. method iterator(Array:D:) {
  83. # something to iterate over in the future
  84. if nqp::getattr(self,List,'$!todo').DEFINITE {
  85. class :: does Iterator {
  86. has int $!i;
  87. has $!array;
  88. has $!reified;
  89. has $!todo;
  90. has $!descriptor;
  91. method !SET-SELF(\array) {
  92. $!i = -1;
  93. $!array := array;
  94. $!reified :=
  95. nqp::ifnull(
  96. nqp::getattr( array,List,'$!reified'),
  97. nqp::bindattr(array,List,'$!reified',
  98. nqp::create(IterationBuffer))
  99. );
  100. $!todo := nqp::getattr(array,List, '$!todo');
  101. $!descriptor := nqp::getattr(array,Array,'$!descriptor');
  102. self
  103. }
  104. method new(\array) { nqp::create(self)!SET-SELF(array) }
  105. method pull-one() is raw {
  106. nqp::ifnull(
  107. nqp::atpos($!reified,$!i = nqp::add_i($!i,1)),
  108. nqp::islt_i($!i,nqp::elems($!reified))
  109. ?? self!hole($!i)
  110. !! $!todo.DEFINITE
  111. ?? nqp::islt_i($!i,$!todo.reify-at-least(nqp::add_i($!i,1)))
  112. ?? nqp::atpos($!reified,$!i) # cannot be nqp::null
  113. !! self!done
  114. !! IterationEnd
  115. )
  116. }
  117. method !hole(int $i) {
  118. nqp::p6bindattrinvres(
  119. (my \v := nqp::p6scalarfromdesc($!descriptor)),
  120. Scalar,
  121. '$!whence',
  122. -> { nqp::bindpos($!reified,$i,v) }
  123. )
  124. }
  125. method !done() is raw {
  126. $!todo := nqp::bindattr($!array,List,'$!todo',Mu);
  127. IterationEnd
  128. }
  129. method push-until-lazy($target) {
  130. nqp::if(
  131. nqp::isconcrete($!todo),
  132. nqp::stmts(
  133. (my int $elems = $!todo.reify-until-lazy),
  134. (my int $i = $!i), # lexicals faster than attributes
  135. nqp::while( # doesn't sink
  136. nqp::islt_i($i = nqp::add_i($i,1),$elems),
  137. $target.push(nqp::atpos($!reified,$i))
  138. ),
  139. nqp::if(
  140. $!todo.fully-reified,
  141. nqp::stmts(
  142. ($!i = $i),
  143. self!done
  144. ),
  145. nqp::stmts(
  146. ($!i = nqp::sub_i($elems,1)),
  147. Mu
  148. )
  149. )
  150. ),
  151. nqp::stmts(
  152. ($elems = nqp::elems($!reified)),
  153. ($i = $!i),
  154. nqp::while( # doesn't sink
  155. nqp::islt_i($i = nqp::add_i($i,1),$elems),
  156. $target.push(
  157. nqp::ifnull(nqp::atpos($!reified,$i),self!hole($i))
  158. )
  159. ),
  160. ($!i = $i),
  161. IterationEnd
  162. )
  163. )
  164. }
  165. method is-lazy() { $!todo.DEFINITE && $!todo.is-lazy }
  166. }.new(self)
  167. }
  168. # everything we need is already there
  169. elsif nqp::getattr(self,List,'$!reified').DEFINITE {
  170. Rakudo::Iterator.ReifiedArray(
  171. self,
  172. nqp::getattr(self,Array,'$!descriptor')
  173. )
  174. }
  175. # nothing now or in the future to iterate over
  176. else {
  177. Rakudo::Iterator.Empty
  178. }
  179. }
  180. method from-iterator(Array:U: Iterator $iter) {
  181. nqp::if(
  182. nqp::eqaddr(
  183. $iter.push-until-lazy(
  184. my \target := ArrayReificationTarget.new(
  185. (my \buffer := nqp::create(IterationBuffer)),
  186. nqp::null
  187. )
  188. ),
  189. IterationEnd
  190. ),
  191. nqp::p6bindattrinvres(nqp::create(self),List,'$!reified',buffer),
  192. nqp::stmts(
  193. nqp::bindattr((my \result := nqp::create(self)),
  194. List,'$!reified',buffer),
  195. nqp::bindattr((my \todo := nqp::create(List::Reifier)),
  196. List::Reifier,'$!current-iter',$iter),
  197. nqp::bindattr(todo,
  198. List::Reifier,'$!reified',buffer),
  199. nqp::bindattr(todo,
  200. List::Reifier,'$!reification-target',target),
  201. nqp::p6bindattrinvres(result,List,'$!todo',todo)
  202. )
  203. )
  204. }
  205. proto method new(|) {*}
  206. multi method new(:$shape!) {
  207. nqp::if(
  208. nqp::defined($shape),
  209. set-shape(self,$shape),
  210. nqp::if(
  211. Metamodel::EnumHOW.ACCEPTS($shape.HOW),
  212. set-shape(self,$shape.^elems),
  213. nqp::create(self)
  214. )
  215. )
  216. }
  217. multi method new() {
  218. nqp::create(self)
  219. }
  220. multi method new(\values, :$shape!) {
  221. nqp::if(
  222. nqp::defined($shape),
  223. set-shape(self,$shape),
  224. nqp::if(
  225. Metamodel::EnumHOW.ACCEPTS($shape.HOW),
  226. set-shape(self,$shape.^elems),
  227. nqp::create(self)
  228. )
  229. ).STORE(values)
  230. }
  231. multi method new(\values) {
  232. nqp::create(self).STORE(values)
  233. }
  234. multi method new(**@values is raw, :$shape!) {
  235. nqp::if(
  236. nqp::defined($shape),
  237. set-shape(self,$shape),
  238. nqp::if(
  239. Metamodel::EnumHOW.ACCEPTS($shape.HOW),
  240. set-shape(self,$shape.^elems),
  241. nqp::create(self)
  242. )
  243. ).STORE(@values)
  244. }
  245. multi method new(**@values is raw) {
  246. nqp::create(self).STORE(@values)
  247. }
  248. proto method STORE(|) {*}
  249. multi method STORE(Array:D: Iterable:D \iterable) {
  250. nqp::iscont(iterable)
  251. ?? self!STORE-ONE(iterable)
  252. !! self!STORE-ITERABLE(iterable)
  253. }
  254. multi method STORE(Array:D: Mu \item) {
  255. self!STORE-ONE(item)
  256. }
  257. method !STORE-ITERABLE(\iterable) {
  258. my \new-storage = nqp::create(IterationBuffer);
  259. my \iter = iterable.iterator;
  260. my \target = ArrayReificationTarget.new(new-storage,
  261. nqp::decont($!descriptor));
  262. if iter.push-until-lazy(target) =:= IterationEnd {
  263. nqp::bindattr(self, List, '$!todo', Mu);
  264. }
  265. else {
  266. my \new-todo = nqp::create(List::Reifier);
  267. nqp::bindattr(new-todo, List::Reifier, '$!reified', new-storage);
  268. nqp::bindattr(new-todo, List::Reifier, '$!current-iter', iter);
  269. nqp::bindattr(new-todo, List::Reifier, '$!reification-target', target);
  270. nqp::bindattr(self, List, '$!todo', new-todo);
  271. }
  272. nqp::bindattr(self, List, '$!reified', new-storage);
  273. self
  274. }
  275. method !STORE-ONE(Mu \item) {
  276. my \new-storage = nqp::create(IterationBuffer);
  277. nqp::push(new-storage,
  278. nqp::assign(nqp::p6scalarfromdesc($!descriptor), item));
  279. nqp::bindattr(self, List, '$!reified', new-storage);
  280. nqp::bindattr(self, List, '$!todo', Mu);
  281. self
  282. }
  283. method reification-target() {
  284. ArrayReificationTarget.new(
  285. nqp::getattr(self, List, '$!reified'),
  286. nqp::decont($!descriptor))
  287. }
  288. multi method Slip(Array:D:) {
  289. # A Slip-With-Default is a special kind of Slip that also has a
  290. # descriptor to be able to generate containers for null elements that
  291. # have type and default information.
  292. my class Slip-With-Descriptor is Slip {
  293. has $!descriptor;
  294. method iterator() {
  295. Rakudo::Iterator.ReifiedArray(self,$!descriptor)
  296. }
  297. method !AT-POS-CONTAINER(Int:D \pos) {
  298. nqp::p6bindattrinvres(
  299. (my $scalar := nqp::p6scalarfromdesc($!descriptor)),
  300. Scalar,
  301. '$!whence',
  302. -> { nqp::bindpos(
  303. nqp::getattr(self,List,'$!reified'),pos,$scalar) }
  304. )
  305. }
  306. multi method AT-POS(Int:D \pos) {
  307. nqp::ifnull(
  308. nqp::atpos(nqp::getattr(self,List,'$!reified'),pos),
  309. self!AT-POS-CONTAINER(pos)
  310. )
  311. }
  312. method default() { $!descriptor.default }
  313. }
  314. BEGIN Slip-With-Descriptor.^set_name("Slip");
  315. nqp::if(
  316. nqp::getattr(self,List,'$!todo').DEFINITE,
  317. # We're not fully reified, and so have internal mutability still.
  318. # The safe thing to do is to take an iterator of ourself and build
  319. # the Slip out of that.
  320. Slip.from-iterator(self.iterator),
  321. # We're fully reified. Make a Slip that shares our reified buffer
  322. # but that will fill in default values for nulls.
  323. nqp::if(
  324. nqp::getattr(self,List,'$!reified').DEFINITE,
  325. nqp::p6bindattrinvres(
  326. nqp::p6bindattrinvres(
  327. nqp::create(Slip-With-Descriptor),
  328. Slip-With-Descriptor,
  329. '$!descriptor',
  330. $!descriptor
  331. ),
  332. List,
  333. '$!reified',
  334. nqp::getattr(self,List,'$!reified')
  335. ),
  336. nqp::create(Slip)
  337. )
  338. )
  339. }
  340. method FLATTENABLE_LIST() {
  341. nqp::if(
  342. nqp::getattr(self,List,'$!todo').DEFINITE,
  343. nqp::stmts(
  344. nqp::getattr(self,List,'$!todo').reify-all,
  345. nqp::getattr(self,List,'$!reified')
  346. ),
  347. nqp::if(
  348. (my $reified := nqp::getattr(self,List,'$!reified')).DEFINITE,
  349. nqp::stmts(
  350. nqp::if(
  351. (my int $elems = nqp::elems($reified)),
  352. nqp::stmts(
  353. (my int $i = -1),
  354. nqp::while(
  355. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  356. nqp::if(
  357. nqp::isnull(nqp::atpos($reified,$i)),
  358. nqp::bindpos(
  359. $reified,
  360. $i,
  361. nqp::p6scalarfromdesc($!descriptor)
  362. )
  363. )
  364. )
  365. )
  366. ),
  367. nqp::getattr(self,List,'$!reified')
  368. ),
  369. nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer))
  370. )
  371. )
  372. }
  373. multi method flat(Array:U:) { self }
  374. multi method flat(Array:D:) { Seq.new(self.iterator) }
  375. multi method List(Array:D: :$view) {
  376. nqp::if(
  377. self.is-lazy, # can't make a List
  378. X::Cannot::Lazy.new(:action<List>).throw,
  379. nqp::if( # all reified
  380. (my $reified := nqp::getattr(self,List,'$!reified')).DEFINITE,
  381. nqp::if(
  382. $view, # assume no change in array
  383. nqp::p6bindattrinvres(
  384. nqp::create(List),List,'$!reified',$reified),
  385. nqp::stmts( # make cow copy
  386. (my int $elems = nqp::elems($reified)),
  387. (my $cow := nqp::setelems(nqp::create(IterationBuffer),$elems)),
  388. (my int $i = -1),
  389. nqp::while(
  390. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  391. nqp::bindpos($cow,$i,nqp::ifnull(nqp::decont(nqp::atpos($reified,$i)),Nil)),
  392. ),
  393. nqp::p6bindattrinvres(nqp::create(List),List,'$!reified',$cow)
  394. )
  395. ),
  396. nqp::create(List) # was empty, is empty
  397. )
  398. )
  399. }
  400. method shape() { (*,) }
  401. multi method AT-POS(Array:D: int $pos) is raw {
  402. nqp::if(
  403. nqp::isge_i($pos,0)
  404. && nqp::isconcrete(nqp::getattr(self,List,'$!reified')),
  405. nqp::ifnull(
  406. nqp::atpos(nqp::getattr(self,List,'$!reified'),$pos),
  407. self!AT-POS-SLOW($pos)
  408. ),
  409. self!AT-POS-SLOW($pos)
  410. )
  411. }
  412. # because this is a very hot path, we copied the code from the int candidate
  413. multi method AT-POS(Array:D: Int:D $pos) is raw {
  414. nqp::if(
  415. nqp::isge_i($pos,0)
  416. && nqp::isconcrete(nqp::getattr(self,List,'$!reified')),
  417. nqp::ifnull(
  418. nqp::atpos(nqp::getattr(self,List,'$!reified'),$pos),
  419. self!AT-POS-SLOW($pos)
  420. ),
  421. self!AT-POS-SLOW($pos)
  422. )
  423. }
  424. # handle any lookup that's not simple
  425. method !AT-POS-SLOW(\pos) is raw {
  426. nqp::if(
  427. nqp::islt_i(pos, 0),
  428. self!index-oor(pos),
  429. nqp::if(
  430. nqp::isconcrete(my $reified := nqp::getattr(self,List,'$!reified')),
  431. nqp::if(
  432. nqp::islt_i(pos,nqp::elems($reified)),
  433. self!AT-POS-CONTAINER(pos), # it's a hole
  434. nqp::if( # too far out, try reifying
  435. nqp::isconcrete(my $todo := nqp::getattr(self,List,'$!todo')),
  436. nqp::stmts(
  437. $todo.reify-at-least(nqp::add_i(pos,1)),
  438. nqp::ifnull(
  439. nqp::atpos($reified,pos), # reified ok
  440. self!AT-POS-CONTAINER(pos) # reifier didn't reach
  441. )
  442. ),
  443. self!AT-POS-CONTAINER(pos) # create an outlander
  444. )
  445. ),
  446. # no reified, implies no todo
  447. nqp::stmts( # create reified
  448. nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer)),
  449. self!AT-POS-CONTAINER(pos) # create an outlander
  450. )
  451. )
  452. )
  453. }
  454. method !AT-POS-CONTAINER(int $pos) is raw {
  455. nqp::p6bindattrinvres(
  456. (my $scalar := nqp::p6scalarfromdesc($!descriptor)),
  457. Scalar,
  458. '$!whence',
  459. -> { nqp::bindpos(nqp::getattr(self,List,'$!reified'),$pos,$scalar) }
  460. )
  461. }
  462. multi method ASSIGN-POS(Array:D: int $pos, Mu \assignee) {
  463. # Fast path: index > 0, $!reified is set up, either have a container
  464. # or no $!todo so can just bind there
  465. my \reified := nqp::getattr(self,List,'$!reified');
  466. nqp::if(
  467. nqp::isge_i($pos, 0) && nqp::isconcrete(reified),
  468. nqp::stmts(
  469. (my \target := nqp::atpos(reified, $pos)),
  470. nqp::if(
  471. nqp::isnull(target),
  472. nqp::if(
  473. nqp::isconcrete(nqp::getattr(self, List, '$!todo')),
  474. self!ASSIGN-POS-SLOW-PATH($pos, assignee),
  475. nqp::assign(
  476. nqp::bindpos(reified, $pos, nqp::p6scalarfromdesc($!descriptor)),
  477. assignee
  478. )
  479. ),
  480. nqp::assign(target, assignee)
  481. )
  482. ),
  483. self!ASSIGN-POS-SLOW-PATH($pos, assignee)
  484. )
  485. }
  486. # because this is a very hot path, we copied the code from the int candidate
  487. multi method ASSIGN-POS(Array:D: Int:D $pos, Mu \assignee) {
  488. # Fast path: index > 0, $!reified is set up, either have a container
  489. # or no $!todo so can just bind there
  490. my \reified := nqp::getattr(self,List,'$!reified');
  491. my int $ipos = $pos;
  492. nqp::if(
  493. nqp::isge_i($ipos, 0) && nqp::isconcrete(reified),
  494. nqp::stmts(
  495. (my \target := nqp::atpos(reified, $ipos)),
  496. nqp::if(
  497. nqp::isnull(target),
  498. nqp::if(
  499. nqp::isconcrete(nqp::getattr(self, List, '$!todo')),
  500. self!ASSIGN-POS-SLOW-PATH($pos, assignee),
  501. nqp::assign(
  502. nqp::bindpos(reified, $ipos, nqp::p6scalarfromdesc($!descriptor)),
  503. assignee
  504. )
  505. ),
  506. nqp::assign(target, assignee)
  507. )
  508. ),
  509. self!ASSIGN-POS-SLOW-PATH($pos, assignee)
  510. )
  511. }
  512. method !ASSIGN-POS-SLOW-PATH(Array:D: Int:D $pos, Mu \assignee) {
  513. nqp::if(
  514. nqp::islt_i($pos,0),
  515. self!index-oor($pos),
  516. nqp::if(
  517. nqp::isconcrete(nqp::getattr(self,List,'$!reified')),
  518. nqp::ifnull(
  519. nqp::atpos(nqp::getattr(self,List,'$!reified'),$pos),
  520. nqp::if(
  521. nqp::islt_i( # it's a hole
  522. $pos,
  523. nqp::elems(nqp::getattr(self,List,'$!reified'))
  524. ),
  525. nqp::bindpos(
  526. nqp::getattr(self,List,'$!reified'),
  527. $pos,
  528. nqp::p6scalarfromdesc($!descriptor)
  529. ),
  530. nqp::if(
  531. nqp::isconcrete(nqp::getattr(self,List,'$!todo')),
  532. nqp::stmts( # can reify
  533. nqp::getattr(self,List,'$!todo')
  534. .reify-at-least(nqp::add_i($pos,1)),
  535. nqp::ifnull(
  536. nqp::atpos( # reified
  537. nqp::getattr(self,List,'$!reified'),
  538. $pos
  539. ),
  540. nqp::bindpos( # outlander
  541. nqp::getattr(self,List,'$!reified'),
  542. $pos,
  543. nqp::p6scalarfromdesc($!descriptor)
  544. )
  545. )
  546. ),
  547. nqp::bindpos( # outlander without todo
  548. nqp::getattr(self,List,'$!reified'),
  549. $pos,
  550. nqp::p6scalarfromdesc($!descriptor)
  551. )
  552. )
  553. )
  554. ),
  555. nqp::bindpos( # new outlander
  556. nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer)),
  557. $pos,
  558. nqp::p6scalarfromdesc($!descriptor)
  559. )
  560. ) = assignee
  561. )
  562. }
  563. multi method BIND-POS(Array:D: int $pos, Mu \bindval) is raw {
  564. nqp::if(
  565. nqp::islt_i($pos,0),
  566. self!index-oor($pos),
  567. nqp::stmts(
  568. nqp::if(
  569. nqp::getattr(self,List,'$!reified').DEFINITE,
  570. nqp::if(
  571. (nqp::isge_i(
  572. $pos,nqp::elems(nqp::getattr(self,List,'$!reified')))
  573. && nqp::getattr(self,List,'$!todo').DEFINITE),
  574. nqp::getattr(self,List,'$!todo').reify-at-least(
  575. nqp::add_i($pos,1)),
  576. ),
  577. nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer))
  578. ),
  579. nqp::bindpos(nqp::getattr(self,List,'$!reified'),$pos,bindval)
  580. )
  581. )
  582. }
  583. # because this is a very hot path, we copied the code from the int candidate
  584. multi method BIND-POS(Array:D: Int:D $pos, Mu \bindval) is raw {
  585. nqp::if(
  586. nqp::islt_i($pos,0),
  587. self!index-oor($pos),
  588. nqp::stmts(
  589. nqp::if(
  590. nqp::getattr(self,List,'$!reified').DEFINITE,
  591. nqp::if(
  592. (nqp::isge_i(
  593. $pos,nqp::elems(nqp::getattr(self,List,'$!reified')))
  594. && nqp::getattr(self,List,'$!todo').DEFINITE),
  595. nqp::getattr(self,List,'$!todo').reify-at-least(
  596. nqp::add_i($pos,1)),
  597. ),
  598. nqp::bindattr(self,List,'$!reified',nqp::create(IterationBuffer))
  599. ),
  600. nqp::bindpos(nqp::getattr(self,List,'$!reified'),$pos,bindval)
  601. )
  602. )
  603. }
  604. multi method DELETE-POS(Array:D: int $pos) is raw {
  605. nqp::if(
  606. nqp::islt_i($pos,0),
  607. self!index-oor($pos),
  608. nqp::if(
  609. (my $reified := nqp::getattr(self,List,'$!reified')).DEFINITE,
  610. nqp::stmts(
  611. nqp::if(
  612. (my $todo := nqp::getattr(self,List,'$!todo')).DEFINITE,
  613. $todo.reify-at-least(nqp::add_i($pos,1)),
  614. ),
  615. nqp::if(
  616. nqp::isle_i( # something to delete
  617. $pos,my int $end = nqp::sub_i(nqp::elems($reified),1)),
  618. nqp::stmts(
  619. (my $value := nqp::ifnull( # save the value
  620. nqp::atpos($reified,$pos),
  621. self.default
  622. )),
  623. nqp::bindpos($reified,$pos,nqp::null), # remove this one
  624. nqp::if(
  625. nqp::iseq_i($pos,$end) && nqp::not_i(nqp::defined($todo)),
  626. nqp::stmts( # shorten from end
  627. (my int $i = $pos),
  628. nqp::while(
  629. (nqp::isge_i(($i = nqp::sub_i($i,1)),0)
  630. && nqp::not_i(nqp::existspos($reified,$i))),
  631. nqp::null
  632. ),
  633. nqp::setelems($reified,nqp::add_i($i,1))
  634. ),
  635. ),
  636. $value # value, if any
  637. ),
  638. self.default # outlander
  639. ),
  640. ),
  641. self.default # no elements
  642. )
  643. )
  644. }
  645. multi method DELETE-POS(Array:D: Int:D $pos) is raw {
  646. self.DELETE-POS(nqp::unbox_i($pos))
  647. }
  648. method !index-oor($pos) {
  649. Failure.new(X::OutOfRange.new(
  650. :what($*INDEX // 'Index'), :got($pos), :range<0..^Inf>
  651. ))
  652. }
  653. # MUST have a separate Slip variant to have it slip
  654. multi method push(Array:D: Slip \value) {
  655. self.is-lazy
  656. ?? X::Cannot::Lazy.new(action => 'push to').throw
  657. !! self!append-list(value)
  658. }
  659. multi method push(Array:D: \value) {
  660. nqp::if(
  661. self.is-lazy,
  662. X::Cannot::Lazy.new(action => 'push to').throw,
  663. nqp::stmts(
  664. nqp::push(
  665. nqp::if(
  666. nqp::getattr(self,List,'$!reified').DEFINITE,
  667. nqp::getattr(self,List,'$!reified'),
  668. nqp::bindattr(self,List,'$!reified',
  669. nqp::create(IterationBuffer))
  670. ),
  671. nqp::assign(nqp::p6scalarfromdesc($!descriptor),value)
  672. ),
  673. self
  674. )
  675. )
  676. }
  677. multi method push(Array:D: **@values is raw) {
  678. self.is-lazy
  679. ?? X::Cannot::Lazy.new(action => 'push to').throw
  680. !! self!append-list(@values)
  681. }
  682. multi method append(Array:D: \value) {
  683. nqp::if(
  684. self.is-lazy,
  685. X::Cannot::Lazy.new(action => 'append to').throw,
  686. nqp::if(
  687. (nqp::iscont(value) || nqp::not_i(nqp::istype(value, Iterable))),
  688. nqp::stmts(
  689. nqp::push(
  690. nqp::if(
  691. nqp::getattr(self,List,'$!reified').DEFINITE,
  692. nqp::getattr(self,List,'$!reified'),
  693. nqp::bindattr(self,List,'$!reified',
  694. nqp::create(IterationBuffer))
  695. ),
  696. nqp::assign(nqp::p6scalarfromdesc($!descriptor),value)
  697. ),
  698. self
  699. ),
  700. self!append-list(value.list)
  701. )
  702. )
  703. }
  704. multi method append(Array:D: **@values is raw) {
  705. self.is-lazy
  706. ?? X::Cannot::Lazy.new(action => 'append to').throw
  707. !! self!append-list(@values)
  708. }
  709. method !append-list(@values) {
  710. nqp::if(
  711. nqp::eqaddr(
  712. @values.iterator.push-until-lazy(
  713. ArrayReificationTarget.new(
  714. nqp::if(
  715. nqp::getattr(self,List,'$!reified').DEFINITE,
  716. nqp::getattr(self,List,'$!reified'),
  717. nqp::bindattr(self,List,'$!reified',
  718. nqp::create(IterationBuffer))
  719. ),
  720. nqp::decont($!descriptor)
  721. )
  722. ),
  723. IterationEnd
  724. ),
  725. self,
  726. X::Cannot::Lazy.new(:action<push>,:what(self.^name)).throw
  727. )
  728. }
  729. multi method unshift(Array:D: Slip \value) {
  730. self!prepend-list(value)
  731. }
  732. multi method unshift(Array:D: \value) {
  733. nqp::stmts(
  734. nqp::unshift(
  735. nqp::if(
  736. nqp::getattr(self,List,'$!reified').DEFINITE,
  737. nqp::getattr(self,List,'$!reified'),
  738. nqp::bindattr(self,List,'$!reified',
  739. nqp::create(IterationBuffer))
  740. ),
  741. nqp::assign(nqp::p6scalarfromdesc($!descriptor),value)
  742. ),
  743. self
  744. )
  745. }
  746. multi method unshift(Array:D: **@values is raw) {
  747. self!prepend-list(@values)
  748. }
  749. multi method prepend(Array:D: \value) {
  750. nqp::if(
  751. (nqp::iscont(value) || nqp::not_i(nqp::istype(value, Iterable))),
  752. nqp::stmts(
  753. nqp::unshift(
  754. nqp::if(
  755. nqp::getattr(self,List,'$!reified').DEFINITE,
  756. nqp::getattr(self,List,'$!reified'),
  757. nqp::bindattr(self,List,'$!reified',
  758. nqp::create(IterationBuffer))
  759. ),
  760. nqp::assign(nqp::p6scalarfromdesc($!descriptor),value)
  761. ),
  762. self
  763. ),
  764. self!prepend-list(value.list)
  765. )
  766. }
  767. multi method prepend(Array:D: **@values is raw) {
  768. self!prepend-list(@values)
  769. }
  770. method !prepend-list(@values) {
  771. nqp::stmts(
  772. nqp::if(
  773. nqp::getattr(self,List,'$!reified').DEFINITE,
  774. nqp::splice(nqp::getattr(self,List,'$!reified'), # prepend existing
  775. nqp::stmts(
  776. @values.iterator.push-all(
  777. ArrayReificationTarget.new(
  778. (my $containers := nqp::create(IterationBuffer)),
  779. nqp::decont($!descriptor)
  780. )
  781. ),
  782. $containers
  783. ),
  784. 0,
  785. 0
  786. ),
  787. @values.iterator.push-all( # no list yet, make this it
  788. ArrayReificationTarget.new(
  789. nqp::bindattr(self,List,'$!reified',
  790. nqp::create(IterationBuffer)),
  791. nqp::decont($!descriptor)
  792. )
  793. )
  794. ),
  795. self
  796. )
  797. }
  798. method pop(Array:D:) is raw is nodal {
  799. nqp::if(
  800. self.is-lazy,
  801. Failure.new(X::Cannot::Lazy.new(action => 'pop from')),
  802. nqp::if(
  803. (nqp::getattr(self,List,'$!reified').DEFINITE
  804. && nqp::elems(nqp::getattr(self,List,'$!reified'))),
  805. nqp::pop(nqp::getattr(self,List,'$!reified')),
  806. Failure.new(X::Cannot::Empty.new(:action<pop>,:what(self.^name)))
  807. )
  808. )
  809. }
  810. method shift(Array:D:) is raw is nodal {
  811. nqp::if(
  812. nqp::getattr(self,List,'$!reified').DEFINITE
  813. && nqp::elems(nqp::getattr(self,List,'$!reified')),
  814. nqp::ifnull( # handle holes
  815. nqp::shift(nqp::getattr(self,List,'$!reified')),
  816. Nil
  817. ),
  818. nqp::if(
  819. (nqp::getattr(self,List,'$!todo').DEFINITE
  820. && nqp::getattr(self,List,'$!todo').reify-at-least(1)),
  821. nqp::shift(nqp::getattr(self,List,'$!reified')),
  822. Failure.new(X::Cannot::Empty.new(:action<shift>,:what(self.^name)))
  823. )
  824. )
  825. }
  826. my $empty := nqp::create(IterationBuffer); # splicing in without values
  827. #------ splice() candidates
  828. multi method splice(Array:D \SELF:) {
  829. nqp::if(
  830. nqp::getattr(SELF,List,'$!reified').DEFINITE,
  831. nqp::stmts(
  832. (my $result := nqp::create(SELF)),
  833. nqp::bindattr($result,Array,'$!descriptor',$!descriptor),
  834. nqp::stmts( # transplant the internals
  835. nqp::bindattr($result,List,'$!reified',
  836. nqp::getattr(SELF,List,'$!reified')),
  837. nqp::if(
  838. nqp::getattr(SELF,List,'$!todo').DEFINITE,
  839. nqp::bindattr($result,List,'$!todo',
  840. nqp::getattr(SELF,List,'$!todo')),
  841. )
  842. ),
  843. (SELF = nqp::create(SELF)), # XXX this preserves $!descriptor ??
  844. $result
  845. ),
  846. nqp::p6bindattrinvres( # nothing to return, so create new one
  847. nqp::create(SELF),Array,'$!descriptor',$!descriptor)
  848. )
  849. }
  850. #------ splice(offset) candidates
  851. multi method splice(Array:D: Whatever $) {
  852. nqp::p6bindattrinvres( # nothing to return, so create new one
  853. nqp::create(self),Array,'$!descriptor',$!descriptor)
  854. }
  855. multi method splice(Array:D: Callable:D $offset) {
  856. self.splice($offset(self.elems))
  857. }
  858. multi method splice(Array:D: Int:D $offset) {
  859. nqp::if(
  860. $offset,
  861. nqp::if(
  862. nqp::islt_i(nqp::unbox_i($offset),0),
  863. self!splice-offset-fail($offset),
  864. nqp::if(
  865. (my $todo := nqp::getattr(self,List,'$!todo')).DEFINITE,
  866. nqp::if(
  867. nqp::isge_i(
  868. $todo.reify-at-least($offset),nqp::unbox_i($offset)),
  869. self!splice-offset(nqp::unbox_i($offset)),
  870. self!splice-offset-fail($offset)
  871. ),
  872. nqp::if(
  873. (nqp::getattr(self,List,'$!reified').DEFINITE
  874. && nqp::isge_i(
  875. nqp::elems(nqp::getattr(self,List,'$!reified')),
  876. nqp::unbox_i($offset))),
  877. self!splice-offset(nqp::unbox_i($offset)),
  878. self!splice-offset-fail($offset)
  879. )
  880. )
  881. ),
  882. self.splice # offset 0, take the quick route out
  883. )
  884. }
  885. method !splice-offset(int $offset) {
  886. nqp::stmts(
  887. (my int $elems = nqp::elems(nqp::getattr(self,List,'$!reified'))),
  888. (my int $size = nqp::sub_i($elems,$offset)),
  889. nqp::bindattr((my $result:= nqp::create(self)),List,'$!reified',
  890. (my $buffer := nqp::setelems(nqp::create(IterationBuffer),$size))),
  891. nqp::bindattr($result,Array,'$!descriptor',$!descriptor),
  892. (my int $i = nqp::sub_i($offset,1)),
  893. nqp::while(
  894. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  895. nqp::bindpos($buffer,nqp::sub_i($i,$offset),
  896. nqp::atpos(nqp::getattr(self,List,'$!reified'),$i))
  897. ),
  898. nqp::splice(
  899. nqp::getattr(self,List,'$!reified'),$empty,$offset,$size),
  900. $result
  901. )
  902. }
  903. method !splice-offset-fail($got) {
  904. X::OutOfRange.new(
  905. :what('Offset argument to splice'), :$got, :range("0..{self.elems}")
  906. ).throw
  907. }
  908. #------ splice(offset,size) candidates
  909. multi method splice(Array:D: Whatever $, Whatever $) {
  910. nqp::p6bindattrinvres( # nothing to return, so create new one
  911. nqp::create(self),Array,'$!descriptor',$!descriptor)
  912. }
  913. multi method splice(Array:D: Whatever $, Int:D $size) {
  914. self.splice(self.elems,$size)
  915. }
  916. multi method splice(Array:D: Whatever $, Callable:D $size) {
  917. my int $elems = self.elems;
  918. self.splice($elems,$size(nqp::sub_i($elems,$elems)));
  919. }
  920. multi method splice(Array:D: Callable:D $offset, Callable:D $size) {
  921. nqp::stmts(
  922. (my int $elems = self.elems),
  923. (my int $from = $offset($elems)),
  924. self.splice($from,$size(nqp::sub_i($elems,$from)))
  925. )
  926. }
  927. multi method splice(Array:D: Callable:D $offset, Whatever $) {
  928. self.splice($offset(self.elems))
  929. }
  930. multi method splice(Array:D: Callable:D $offset, Int:D $size) {
  931. self.splice($offset(self.elems),$size)
  932. }
  933. multi method splice(Array:D: Int:D $offset, Whatever $) {
  934. self.splice($offset)
  935. }
  936. multi method splice(Array:D: Int:D $offset, Callable:D $size) {
  937. self.splice($offset,$size(self.elems - $offset))
  938. }
  939. multi method splice(Array:D: Int:D $offset, Int:D $size) {
  940. nqp::if(
  941. nqp::islt_i(nqp::unbox_i($offset),0),
  942. self!splice-offset-fail($offset),
  943. nqp::if(
  944. nqp::islt_i(nqp::unbox_i($size),0),
  945. self!splice-size-fail($size,$offset),
  946. nqp::if(
  947. (my $todo := nqp::getattr(self,List,'$!todo')).DEFINITE,
  948. nqp::if(
  949. nqp::isge_i(
  950. $todo.reify-at-least(
  951. nqp::add_i(nqp::unbox_i($offset),nqp::unbox_i($size))
  952. ),nqp::unbox_i($offset)),
  953. self!splice-offset-size(
  954. nqp::unbox_i($offset),nqp::unbox_i($size)),
  955. self!splice-size-fail($size,$offset)
  956. ),
  957. nqp::if(
  958. nqp::getattr(self,List,'$!reified').DEFINITE,
  959. nqp::if(
  960. nqp::isge_i(
  961. nqp::elems(nqp::getattr(self,List,'$!reified')),
  962. nqp::unbox_i($offset)),
  963. self!splice-offset-size(
  964. nqp::unbox_i($offset),nqp::unbox_i($size)),
  965. self!splice-size-fail($size,$offset)
  966. ),
  967. nqp::if(
  968. nqp::iseq_i(nqp::unbox_i($offset),0),
  969. nqp::p6bindattrinvres( # nothing to return, create new
  970. nqp::create(self),Array,'$!descriptor',$!descriptor),
  971. self!splice-offset-fail($offset)
  972. )
  973. )
  974. )
  975. )
  976. )
  977. }
  978. method !splice-offset-size(int $offset,int $size) {
  979. nqp::stmts(
  980. (my $result := self!splice-save($offset,$size,my int $removed)),
  981. nqp::splice(
  982. nqp::getattr(self,List,'$!reified'),$empty,$offset,$removed),
  983. $result
  984. )
  985. }
  986. method !splice-save(int $offset,int $size, \removed) {
  987. nqp::stmts(
  988. (removed = nqp::if(
  989. nqp::isgt_i(
  990. nqp::add_i($offset,$size),
  991. nqp::elems(nqp::getattr(self,List,'$!reified'))
  992. ),
  993. nqp::sub_i(nqp::elems(nqp::getattr(self,List,'$!reified')),$offset),
  994. $size
  995. )),
  996. nqp::if(
  997. removed,
  998. nqp::stmts(
  999. nqp::bindattr((my $saved:= nqp::create(self)),List,'$!reified',
  1000. (my $buffer :=
  1001. nqp::setelems(nqp::create(IterationBuffer),removed))),
  1002. nqp::bindattr($saved,Array,'$!descriptor',$!descriptor),
  1003. (my int $i = -1),
  1004. nqp::while(
  1005. nqp::islt_i(($i = nqp::add_i($i,1)),removed),
  1006. nqp::bindpos($buffer,$i,nqp::atpos(
  1007. nqp::getattr(self,List,'$!reified'),nqp::add_i($offset,$i)))
  1008. ),
  1009. $saved
  1010. ),
  1011. nqp::p6bindattrinvres( # effective size = 0, create new one
  1012. nqp::create(self),Array,'$!descriptor',$!descriptor)
  1013. )
  1014. )
  1015. }
  1016. method !splice-size-fail($got,$offset) {
  1017. nqp::if(
  1018. $offset > self.elems,
  1019. self!splice-offset-fail($offset),
  1020. X::OutOfRange.new(
  1021. :what('Size argument to splice'),
  1022. :$got,
  1023. :range("0..^{self.elems - $offset}")
  1024. ).throw
  1025. )
  1026. }
  1027. #------ splice(offset,size,array) candidates
  1028. # we have these 9 multies to avoid infiniloop when incorrect types are
  1029. # given to $offset/$size. Other attempts to resolve this showed 30%+
  1030. # performance decreases
  1031. multi method splice(Array:D: Whatever $offset, Whatever $size, **@new) { self.splice($offset, $size, @new) }
  1032. multi method splice(Array:D: Whatever $offset, Callable:D $size, **@new) { self.splice($offset, $size, @new) }
  1033. multi method splice(Array:D: Whatever $offset, Int:D $size, **@new) { self.splice($offset, $size, @new) }
  1034. multi method splice(Array:D: Callable:D $offset, Whatever $size, **@new) { self.splice($offset, $size, @new) }
  1035. multi method splice(Array:D: Callable:D $offset, Callable:D $size, **@new) { self.splice($offset, $size, @new) }
  1036. multi method splice(Array:D: Callable:D $offset, Int:D $size, **@new) { self.splice($offset, $size, @new) }
  1037. multi method splice(Array:D: Int:D $offset, Whatever $size, **@new) { self.splice($offset, $size, @new) }
  1038. multi method splice(Array:D: Int:D $offset, Callable:D $size, **@new) { self.splice($offset, $size, @new) }
  1039. multi method splice(Array:D: Int:D $offset, Int:D $size, **@new) { self.splice($offset, $size, @new) }
  1040. multi method splice(Array:D: Whatever $, Whatever $, @new) {
  1041. self.splice(self.elems,0,@new)
  1042. }
  1043. multi method splice(Array:D: Whatever $, Int:D $size, @new) {
  1044. self.splice(self.elems,$size,@new)
  1045. }
  1046. multi method splice(Array:D: Whatever $, Callable:D $size, @new) {
  1047. my int $elems = self.elems;
  1048. self.splice($elems,$size(nqp::sub_i($elems,$elems)),@new);
  1049. }
  1050. multi method splice(Array:D: Callable:D $offset, Callable:D $size, @new) {
  1051. nqp::stmts(
  1052. (my int $elems = self.elems),
  1053. (my int $from = $offset($elems)),
  1054. self.splice($from,$size(nqp::sub_i($elems,$from)),@new)
  1055. )
  1056. }
  1057. multi method splice(Array:D: Callable:D $offset, Whatever $, @new) {
  1058. nqp::stmts(
  1059. (my int $elems = self.elems),
  1060. (my int $from = $offset($elems)),
  1061. self.splice($from,nqp::sub_i($elems,$from),@new)
  1062. )
  1063. }
  1064. multi method splice(Array:D: Callable:D $offset, Int:D $size, @new) {
  1065. self.splice($offset(self.elems),$size,@new)
  1066. }
  1067. multi method splice(Array:D: Int:D $offset, Whatever $, @new) {
  1068. self.splice($offset,self.elems - $offset,@new)
  1069. }
  1070. multi method splice(Array:D: Int:D $offset, Callable:D $size, @new) {
  1071. self.splice($offset,$size(self.elems - $offset),@new)
  1072. }
  1073. multi method splice(Array:D: Int:D $offset, Int:D $size, @new) {
  1074. nqp::if(
  1075. nqp::islt_i(nqp::unbox_i($offset),0),
  1076. self!splice-offset-fail($offset),
  1077. nqp::if(
  1078. nqp::islt_i(nqp::unbox_i($size),0),
  1079. self!splice-size-fail($size,$offset),
  1080. nqp::if(
  1081. (my $todo := nqp::getattr(self,List,'$!todo')).DEFINITE,
  1082. nqp::if(
  1083. nqp::isge_i(
  1084. $todo.reify-at-least(
  1085. nqp::add_i(nqp::unbox_i($offset),nqp::unbox_i($size))
  1086. ),nqp::unbox_i($offset)),
  1087. self!splice-offset-size-new(
  1088. nqp::unbox_i($offset),nqp::unbox_i($size),@new),
  1089. self!splice-size-fail($size,$offset)
  1090. ),
  1091. nqp::if(
  1092. nqp::isge_i(
  1093. nqp::elems(nqp::if(
  1094. nqp::getattr(self,List,'$!reified').DEFINITE,
  1095. nqp::getattr(self,List,'$!reified'),
  1096. nqp::bindattr(self,List,'$!reified',
  1097. nqp::create(IterationBuffer))
  1098. )),
  1099. nqp::unbox_i($offset),
  1100. ),
  1101. self!splice-offset-size-new(
  1102. nqp::unbox_i($offset),nqp::unbox_i($size),@new),
  1103. self!splice-offset-fail($offset)
  1104. )
  1105. )
  1106. )
  1107. )
  1108. }
  1109. method !splice-offset-size-new(int $offset,int $size,@new) {
  1110. nqp::if(
  1111. nqp::eqaddr(@new.iterator.push-until-lazy(
  1112. (my $new := IterationBuffer.new)),IterationEnd),
  1113. nqp::if( # reified all values to splice in
  1114. (nqp::isnull($!descriptor) || nqp::eqaddr(self.of,Mu)),
  1115. nqp::stmts( # no typecheck needed
  1116. (my $result := self!splice-save($offset,$size,my int $removed)),
  1117. nqp::splice(
  1118. nqp::getattr(self,List,'$!reified'),$new,$offset,$removed),
  1119. $result
  1120. ),
  1121. nqp::stmts( # typecheck the values first
  1122. (my $expected := self.of),
  1123. (my int $elems = nqp::elems($new)),
  1124. (my int $i = -1),
  1125. nqp::while(
  1126. (nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  1127. && nqp::istype(nqp::atpos($new,$i),$expected)),
  1128. nqp::null
  1129. ),
  1130. nqp::if(
  1131. nqp::islt_i($i,$elems), # exited loop because of wrong type
  1132. X::TypeCheck::Splice.new(
  1133. :action<splice>,
  1134. :got(nqp::atpos($new,$i).WHAT),
  1135. :$expected
  1136. ).throw,
  1137. nqp::stmts(
  1138. ($result := self!splice-save($offset,$size,$removed)),
  1139. nqp::splice(
  1140. nqp::getattr(self,List,'$!reified'),$new,$offset,$removed),
  1141. $result
  1142. )
  1143. )
  1144. )
  1145. ),
  1146. X::Cannot::Lazy.new(:action('splice in')).throw
  1147. )
  1148. }
  1149. multi method tail(Array:D: $n) {
  1150. nqp::if(
  1151. nqp::getattr(self,List,'$!todo').DEFINITE,
  1152. self.Any::tail($n),
  1153. Seq.new(
  1154. nqp::if(
  1155. (my $reified := nqp::getattr(self,List,'$!reified')).DEFINITE
  1156. && nqp::elems($reified),
  1157. nqp::stmts(
  1158. (my $iterator := Rakudo::Iterator.ReifiedArray(
  1159. self,
  1160. nqp::getattr(self,Array,'$!descriptor')
  1161. )),
  1162. nqp::if(
  1163. nqp::istype($n,Callable)
  1164. && nqp::isgt_i((my $skip := -($n(0).Int)),0),
  1165. $iterator.skip-at-least($skip),
  1166. nqp::unless(
  1167. nqp::istype($n,Whatever) || $n == Inf,
  1168. $iterator.skip-at-least(nqp::elems($reified) - $n)
  1169. )
  1170. ),
  1171. $iterator
  1172. ),
  1173. Rakudo::Iterator.Empty
  1174. )
  1175. )
  1176. )
  1177. }
  1178. # introspection
  1179. method name() {
  1180. nqp::isnull($!descriptor) ?? Nil !! $!descriptor.name
  1181. }
  1182. method of() {
  1183. nqp::isnull($!descriptor) ?? Mu !! $!descriptor.of
  1184. }
  1185. method default() {
  1186. nqp::isnull($!descriptor) ?? Any !! $!descriptor.default
  1187. }
  1188. method dynamic() {
  1189. nqp::isnull($!descriptor) ?? False !! so $!descriptor.dynamic
  1190. }
  1191. multi method perl(Array:D \SELF:) {
  1192. SELF.perlseen('Array', {
  1193. '$' x nqp::iscont(SELF) # self is always deconted
  1194. ~ '['
  1195. ~ self.map({nqp::decont($_).perl}).join(', ')
  1196. ~ ',' x (self.elems == 1 && nqp::istype(self.AT-POS(0),Iterable))
  1197. ~ ']'
  1198. })
  1199. }
  1200. multi method WHICH(Array:D:) { self.Mu::WHICH }
  1201. #=============== class Array is closed in src/core/TypedArray.pm6 ==============