1. # all sub postcircumfix [;] candidates here please
  2. proto sub postcircumfix:<[; ]>(|) is nodal {*}
  3. sub MD-ARRAY-SLICE-ONE-POSITION(\SELF, \indices, \idx, int $dim, \target) is raw {
  4. my int $next-dim = $dim + 1;
  5. if $next-dim < indices.elems {
  6. if nqp::istype(idx, Iterable) && !nqp::iscont(idx) {
  7. for idx {
  8. MD-ARRAY-SLICE-ONE-POSITION(SELF, indices, $_, $dim, target)
  9. }
  10. }
  11. elsif nqp::istype(idx, Int) {
  12. MD-ARRAY-SLICE-ONE-POSITION(SELF.AT-POS(idx), indices, indices.AT-POS($next-dim), $next-dim, target)
  13. }
  14. elsif nqp::istype(idx, Whatever) {
  15. for ^SELF.elems {
  16. MD-ARRAY-SLICE-ONE-POSITION(SELF.AT-POS($_), indices, indices.AT-POS($next-dim), $next-dim, target)
  17. }
  18. }
  19. elsif nqp::istype(idx, Callable) {
  20. MD-ARRAY-SLICE-ONE-POSITION(SELF, indices, idx.(|(SELF.elems xx (idx.count == Inf ?? 1 !! idx.count))), $dim, target);
  21. }
  22. else {
  23. MD-ARRAY-SLICE-ONE-POSITION(SELF.AT-POS(idx.Int), indices, indices.AT-POS($next-dim), $next-dim, target)
  24. }
  25. }
  26. else {
  27. if nqp::istype(idx, Iterable) && !nqp::iscont(idx) {
  28. for idx {
  29. MD-ARRAY-SLICE-ONE-POSITION(SELF, indices, $_, $dim, target)
  30. }
  31. }
  32. elsif nqp::istype(idx, Int) {
  33. nqp::push(target, SELF.AT-POS(idx))
  34. }
  35. elsif nqp::istype(idx, Whatever) {
  36. for ^SELF.elems {
  37. nqp::push(target, SELF.AT-POS($_))
  38. }
  39. }
  40. elsif nqp::istype(idx, Callable) {
  41. nqp::push(target, SELF.AT-POS(idx.(|(SELF.elems xx (idx.count == Inf ?? 1 !! idx.count)))))
  42. }
  43. else {
  44. nqp::push(target, SELF.AT-POS(idx.Int))
  45. }
  46. }
  47. }
  48. sub MD-ARRAY-SLICE(\SELF, @indices) is raw {
  49. my \target = IterationBuffer.new;
  50. MD-ARRAY-SLICE-ONE-POSITION(SELF, @indices, @indices.AT-POS(0), 0, target);
  51. nqp::p6bindattrinvres(nqp::create(List), List, '$!reified', target)
  52. }
  53. multi sub postcircumfix:<[; ]>(\SELF, @indices) is raw {
  54. nqp::stmts(
  55. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  56. (my int $elems = nqp::elems($indices)),
  57. (my int $i = -1),
  58. (my $idxs := nqp::list_i),
  59. nqp::while(
  60. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  61. nqp::if(
  62. nqp::istype((my $index := nqp::atpos($indices,$i)),Int),
  63. nqp::push_i($idxs,$index), # it's an Int, use that
  64. nqp::if(
  65. nqp::istype($index,Numeric),
  66. nqp::push_i($idxs,$index.Int), # can be safely coerced to Int
  67. nqp::if(
  68. nqp::istype($index,Str),
  69. nqp::if(
  70. nqp::istype((my $coerced := $index.Int),Failure),
  71. $coerced.throw, # alas, not numeric, bye!
  72. nqp::push_i($idxs,$coerced) # could be coerced to Int
  73. ),
  74. (return-rw MD-ARRAY-SLICE(SELF,@indices)) # alas, slow path needed
  75. )
  76. )
  77. )
  78. ),
  79. nqp::if( # we have all Ints
  80. nqp::iseq_i($elems,2),
  81. SELF.AT-POS( # fast pathing [n;n]
  82. nqp::atpos_i($idxs,0),
  83. nqp::atpos_i($idxs,1)
  84. ),
  85. nqp::if(
  86. nqp::iseq_i($elems,3),
  87. SELF.AT-POS( # fast pathing [n;n;n]
  88. nqp::atpos_i($idxs,0),
  89. nqp::atpos_i($idxs,1),
  90. nqp::atpos_i($idxs,2)
  91. ),
  92. SELF.AT-POS(|@indices) # alas >3 dims, slow path
  93. )
  94. )
  95. )
  96. }
  97. multi sub postcircumfix:<[; ]>(\SELF, @indices, Mu \assignee) is raw {
  98. nqp::stmts(
  99. (my int $elems = @indices.elems), # reifies
  100. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  101. (my int $i = -1),
  102. nqp::while(
  103. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  104. && nqp::istype(nqp::atpos($indices,$i),Int),
  105. nqp::null
  106. ),
  107. nqp::if(
  108. nqp::islt_i($i,$elems),
  109. (MD-ARRAY-SLICE(SELF,@indices) = assignee),
  110. nqp::if(
  111. nqp::iseq_i($elems,2),
  112. SELF.ASSIGN-POS(
  113. nqp::atpos($indices,0),
  114. nqp::atpos($indices,1),
  115. assignee
  116. ),
  117. nqp::if(
  118. nqp::iseq_i($elems,3),
  119. SELF.ASSIGN-POS(
  120. nqp::atpos($indices,0),
  121. nqp::atpos($indices,1),
  122. nqp::atpos($indices,2),
  123. assignee
  124. ),
  125. SELF.ASSIGN-POS(|@indices,assignee)
  126. )
  127. )
  128. )
  129. )
  130. }
  131. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$BIND!) is raw {
  132. nqp::stmts(
  133. (my int $elems = @indices.elems), # reifies
  134. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  135. (my int $i = -1),
  136. nqp::while(
  137. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  138. && nqp::istype(nqp::atpos($indices,$i),Int),
  139. nqp::null
  140. ),
  141. nqp::if(
  142. nqp::islt_i($i,$elems),
  143. X::Bind::Slice.new(type => SELF.WHAT).throw,
  144. nqp::if(
  145. nqp::iseq_i($elems,2),
  146. SELF.BIND-POS(
  147. nqp::atpos($indices,0),
  148. nqp::atpos($indices,1),
  149. $BIND
  150. ),
  151. nqp::if(
  152. nqp::iseq_i($elems,3),
  153. SELF.BIND-POS(
  154. nqp::atpos($indices,0),
  155. nqp::atpos($indices,1),
  156. nqp::atpos($indices,2),
  157. $BIND
  158. ),
  159. SELF.BIND-POS(|@indices, $BIND)
  160. )
  161. )
  162. )
  163. )
  164. }
  165. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$delete!) is raw {
  166. nqp::if(
  167. $delete,
  168. nqp::stmts(
  169. (my int $elems = @indices.elems), # reifies
  170. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  171. (my int $i = -1),
  172. nqp::while(
  173. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  174. && nqp::istype(nqp::atpos($indices,$i),Int),
  175. nqp::null
  176. ),
  177. nqp::if(
  178. nqp::islt_i($i,$elems),
  179. Failure.new(X::NYI.new(
  180. feature => ':delete on multi-dimensional slices')),
  181. nqp::if(
  182. nqp::iseq_i($elems,2),
  183. SELF.DELETE-POS(
  184. nqp::atpos($indices,0),
  185. nqp::atpos($indices,1)
  186. ),
  187. nqp::if(
  188. nqp::iseq_i($elems,3),
  189. SELF.DELETE-POS(
  190. nqp::atpos($indices,0),
  191. nqp::atpos($indices,1),
  192. nqp::atpos($indices,2)
  193. ),
  194. SELF.DELETE-POS(|@indices)
  195. )
  196. )
  197. )
  198. ),
  199. postcircumfix:<[; ]>(SELF, @indices)
  200. )
  201. }
  202. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$exists!) is raw {
  203. nqp::if(
  204. $exists,
  205. nqp::stmts(
  206. (my int $elems = @indices.elems), # reifies
  207. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  208. (my int $i = -1),
  209. nqp::while(
  210. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  211. && nqp::istype(nqp::atpos($indices,$i),Int),
  212. nqp::null
  213. ),
  214. nqp::if(
  215. nqp::islt_i($i,$elems),
  216. Failure.new(X::NYI.new(
  217. feature => ':exists on multi-dimensional slices')),
  218. nqp::if(
  219. nqp::iseq_i($elems,2),
  220. SELF.EXISTS-POS(
  221. nqp::atpos($indices,0),
  222. nqp::atpos($indices,1)
  223. ),
  224. nqp::if(
  225. nqp::iseq_i($elems,3),
  226. SELF.EXISTS-POS(
  227. nqp::atpos($indices,0),
  228. nqp::atpos($indices,1),
  229. nqp::atpos($indices,2)
  230. ),
  231. SELF.EXISTS-POS(|@indices)
  232. )
  233. )
  234. )
  235. ),
  236. postcircumfix:<[; ]>(SELF, @indices)
  237. )
  238. }
  239. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$kv!) is raw {
  240. nqp::if(
  241. $kv,
  242. nqp::stmts(
  243. (my int $elems = @indices.elems), # reifies
  244. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  245. (my int $i = -1),
  246. nqp::while(
  247. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  248. && nqp::istype(nqp::atpos($indices,$i),Int),
  249. nqp::null
  250. ),
  251. nqp::if(
  252. nqp::islt_i($i,$elems),
  253. Failure.new(X::NYI.new(
  254. feature => ':kv on multi-dimensional slices')),
  255. nqp::if(
  256. nqp::iseq_i($elems,2),
  257. nqp::if(
  258. SELF.EXISTS-POS(
  259. nqp::atpos($indices,0),
  260. nqp::atpos($indices,1)
  261. ),
  262. (@indices, SELF.AT-POS(
  263. nqp::atpos($indices,0),
  264. nqp::atpos($indices,1)
  265. )),
  266. ()
  267. ),
  268. nqp::if(
  269. nqp::iseq_i($elems,3),
  270. nqp::if(
  271. SELF.EXISTS-POS(
  272. nqp::atpos($indices,0),
  273. nqp::atpos($indices,1),
  274. nqp::atpos($indices,2)
  275. ),
  276. (@indices, SELF.AT-POS(
  277. nqp::atpos($indices,0),
  278. nqp::atpos($indices,1),
  279. nqp::atpos($indices,2)
  280. )),
  281. ()
  282. ),
  283. nqp::if(
  284. SELF.EXISTS-POS(|@indices),
  285. (@indices, SELF.AT-POS(|@indices)),
  286. ()
  287. )
  288. )
  289. )
  290. )
  291. ),
  292. postcircumfix:<[; ]>(SELF, @indices)
  293. )
  294. }
  295. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$p!) is raw {
  296. nqp::if(
  297. $p,
  298. nqp::stmts(
  299. (my int $elems = @indices.elems), # reifies
  300. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  301. (my int $i = -1),
  302. nqp::while(
  303. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  304. && nqp::istype(nqp::atpos($indices,$i),Int),
  305. nqp::null
  306. ),
  307. nqp::if(
  308. nqp::islt_i($i,$elems),
  309. Failure.new(X::NYI.new(
  310. feature => ':p on multi-dimensional slices')),
  311. nqp::if(
  312. nqp::iseq_i($elems,2),
  313. nqp::if(
  314. SELF.EXISTS-POS(
  315. nqp::atpos($indices,0),
  316. nqp::atpos($indices,1)
  317. ),
  318. Pair.new(@indices, SELF.AT-POS(
  319. nqp::atpos($indices,0),
  320. nqp::atpos($indices,1)
  321. )),
  322. ()
  323. ),
  324. nqp::if(
  325. nqp::iseq_i($elems,3),
  326. nqp::if(
  327. SELF.EXISTS-POS(
  328. nqp::atpos($indices,0),
  329. nqp::atpos($indices,1),
  330. nqp::atpos($indices,2)
  331. ),
  332. Pair.new(@indices, SELF.AT-POS(
  333. nqp::atpos($indices,0),
  334. nqp::atpos($indices,1),
  335. nqp::atpos($indices,2)
  336. )),
  337. ()
  338. ),
  339. nqp::if(
  340. SELF.EXISTS-POS(|@indices),
  341. Pair.new(@indices, SELF.AT-POS(|@indices)),
  342. ()
  343. )
  344. )
  345. )
  346. )
  347. ),
  348. postcircumfix:<[; ]>(SELF, @indices)
  349. )
  350. }
  351. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$k!) is raw {
  352. nqp::if(
  353. $k,
  354. nqp::stmts(
  355. (my int $elems = @indices.elems), # reifies
  356. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  357. (my int $i = -1),
  358. nqp::while(
  359. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  360. && nqp::istype(nqp::atpos($indices,$i),Int),
  361. nqp::null
  362. ),
  363. nqp::if(
  364. nqp::islt_i($i,$elems),
  365. Failure.new(X::NYI.new(
  366. feature => ':k on multi-dimensional slices')),
  367. nqp::if(
  368. nqp::iseq_i($elems,2),
  369. nqp::if(
  370. SELF.EXISTS-POS(
  371. nqp::atpos($indices,0),
  372. nqp::atpos($indices,1)
  373. ),
  374. @indices,
  375. ()
  376. ),
  377. nqp::if(
  378. nqp::iseq_i($elems,3),
  379. nqp::if(
  380. SELF.EXISTS-POS(
  381. nqp::atpos($indices,0),
  382. nqp::atpos($indices,1),
  383. nqp::atpos($indices,2)
  384. ),
  385. @indices,
  386. ()
  387. ),
  388. nqp::if(
  389. SELF.EXISTS-POS(|@indices),
  390. @indices,
  391. ()
  392. )
  393. )
  394. )
  395. )
  396. ),
  397. postcircumfix:<[; ]>(SELF, @indices)
  398. )
  399. }
  400. multi sub postcircumfix:<[; ]>(\SELF, @indices, :$v!) is raw {
  401. nqp::if(
  402. $v,
  403. nqp::stmts(
  404. (my int $elems = @indices.elems), # reifies
  405. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  406. (my int $i = -1),
  407. nqp::while(
  408. nqp::islt_i(($i = nqp::add_i($i,1)),$elems)
  409. && nqp::istype(nqp::atpos($indices,$i),Int),
  410. nqp::null
  411. ),
  412. nqp::if(
  413. nqp::islt_i($i,$elems),
  414. Failure.new(X::NYI.new(
  415. feature => ':v on multi-dimensional slices')),
  416. nqp::if(
  417. nqp::iseq_i($elems,2),
  418. nqp::if(
  419. SELF.EXISTS-POS(
  420. nqp::atpos($indices,0),
  421. nqp::atpos($indices,1)
  422. ),
  423. nqp::decont(SELF.AT-POS(
  424. nqp::atpos($indices,0),
  425. nqp::atpos($indices,1)
  426. )),
  427. ()
  428. ),
  429. nqp::if(
  430. nqp::iseq_i($elems,3),
  431. nqp::if(
  432. SELF.EXISTS-POS(
  433. nqp::atpos($indices,0),
  434. nqp::atpos($indices,1),
  435. nqp::atpos($indices,2)
  436. ),
  437. nqp::decont(SELF.AT-POS(
  438. nqp::atpos($indices,0),
  439. nqp::atpos($indices,1),
  440. nqp::atpos($indices,2)
  441. )),
  442. ()
  443. ),
  444. nqp::if(
  445. SELF.EXISTS-POS(|@indices),
  446. nqp::decont(SELF.AT-POS(|@indices)),
  447. ()
  448. )
  449. )
  450. )
  451. )
  452. ),
  453. postcircumfix:<[; ]>(SELF, @indices)
  454. )
  455. }