1. # all sub postcircumfix [] candidates here please
  2. # Generates list of positions to index into the array at. Takes all those
  3. # before something lazy is encountered and eagerly reifies them. If there
  4. # are any lazy things in the slice, then we lazily consider those, but will
  5. # truncate at the first one that is out of range. The optional
  6. # :$eagerize will be called if Whatever/WhateverCode is encountered or if
  7. # clipping of lazy indices is enacted. It should return the number of
  8. # elements of the array if called with Whatever, or do something EXISTS-POSish
  9. # if called with an Int. Before it does so, it may cause the calling code
  10. # to switch to a memoized version of an iterator by modifying variables in
  11. # the caller's scope.
  12. proto sub POSITIONS(|) {*}
  13. multi sub POSITIONS(
  14. \SELF,
  15. \pos,
  16. Callable :$eagerize = -> \idx {
  17. nqp::if(
  18. nqp::istype(idx,Whatever),
  19. nqp::if(nqp::isconcrete(SELF),SELF.elems,0),
  20. SELF.EXISTS-POS(idx)
  21. )
  22. }
  23. ) {
  24. my class IndicesReificationTarget {
  25. has $!target;
  26. has $!star;
  27. method new(\target, \star) {
  28. my \rt = nqp::create(self);
  29. nqp::bindattr(rt, self, '$!target', target);
  30. nqp::bindattr(rt, self, '$!star', star);
  31. rt
  32. }
  33. method push(Mu \value) {
  34. nqp::if(
  35. nqp::istype(value,Callable),
  36. nqp::stmts(
  37. nqp::if(
  38. nqp::istype($!star,Callable),
  39. nqp::bindattr(self,IndicesReificationTarget,'$!star',$!star(*))
  40. ),
  41. # just using value(...) causes stage optimize to die
  42. (my &whatever := value),
  43. nqp::if(
  44. &whatever.count == Inf,
  45. nqp::push($!target, whatever(+$!star)),
  46. nqp::push($!target, whatever(|(+$!star xx &whatever.count)))
  47. )
  48. ),
  49. nqp::push($!target,value)
  50. )
  51. }
  52. }
  53. # we can optimize `42..*` Ranges; as long as they're from core, unmodified
  54. my \is-pos-lazy = pos.is-lazy;
  55. my \pos-iter = nqp::eqaddr(pos.WHAT,Range)
  56. && nqp::eqaddr(pos.max,Inf)
  57. && nqp::isfalse(SELF.is-lazy)
  58. ?? Range.new(pos.min, SELF.elems-1,
  59. :excludes-min(pos.excludes-min),
  60. :excludes-max(pos.excludes-max)
  61. ).iterator
  62. !! pos.iterator;
  63. my \pos-list = nqp::create(List);
  64. my \eager-indices = nqp::create(IterationBuffer);
  65. my \target = IndicesReificationTarget.new(eager-indices, $eagerize);
  66. nqp::bindattr(pos-list, List, '$!reified', eager-indices);
  67. if is-pos-lazy {
  68. # With lazy indices, we truncate at the first one that fails to exists.
  69. my \rest-seq = Seq.new(pos-iter).flatmap: -> Int() $i {
  70. nqp::unless(
  71. $eagerize($i),
  72. last,
  73. $i
  74. )
  75. };
  76. my \todo := nqp::create(List::Reifier);
  77. nqp::bindattr(todo, List::Reifier, '$!reified', eager-indices);
  78. nqp::bindattr(todo, List::Reifier, '$!current-iter', rest-seq.iterator);
  79. nqp::bindattr(todo, List::Reifier, '$!reification-target', eager-indices);
  80. nqp::bindattr(pos-list, List, '$!todo', todo);
  81. }
  82. else {
  83. pos-iter.push-all: target;
  84. }
  85. pos-list
  86. }
  87. proto sub postcircumfix:<[ ]>(|) is nodal {*}
  88. multi sub postcircumfix:<[ ]>( \SELF, Any:U $type, |c ) is raw {
  89. die "Unable to call postcircumfix {try SELF.VAR.name}[ $type.gist() ] with a type object\n"
  90. ~ "Indexing requires a defined object";
  91. }
  92. # @a[int 1]
  93. multi sub postcircumfix:<[ ]>( \SELF, int $pos ) is raw {
  94. SELF.AT-POS($pos);
  95. }
  96. multi sub postcircumfix:<[ ]>( \SELF, int $pos, Mu \assignee ) is raw {
  97. SELF.ASSIGN-POS($pos, assignee);
  98. }
  99. multi sub postcircumfix:<[ ]>(\SELF, int $pos, Mu :$BIND! is raw) is raw {
  100. SELF.BIND-POS($pos, $BIND);
  101. }
  102. multi sub postcircumfix:<[ ]>( \SELF, int $pos, :$delete!, *%other ) is raw {
  103. $delete && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  104. ?? SELF.DELETE-POS($pos)
  105. !! SLICE_ONE_LIST( SELF, $pos, 'delete', $delete, %other );
  106. }
  107. multi sub postcircumfix:<[ ]>( \SELF, int $pos, :$exists!, *%other ) is raw {
  108. $exists && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  109. ?? SELF.EXISTS-POS($pos)
  110. !! SLICE_ONE_LIST( SELF, $pos, 'exists', $exists, %other );
  111. }
  112. multi sub postcircumfix:<[ ]>( \SELF, int $pos, :$kv!, *%other ) is raw {
  113. $kv && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  114. ?? (SELF.EXISTS-POS($pos) ?? ($pos, SELF.AT-POS($pos)) !! ())
  115. !! SLICE_ONE_LIST( SELF, $pos, 'kv', $kv, %other );
  116. }
  117. multi sub postcircumfix:<[ ]>( \SELF, int $pos, :$p!, *%other ) is raw {
  118. $p && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  119. ?? (SELF.EXISTS-POS($pos) ?? Pair.new($pos,SELF.AT-POS($pos)) !! ())
  120. !! SLICE_ONE_LIST( SELF, $pos, 'p', $p, %other );
  121. }
  122. multi sub postcircumfix:<[ ]>( \SELF, int $pos, :$k!, *%other ) is raw {
  123. $k && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  124. ?? (SELF.EXISTS-POS($pos) ?? $pos !! ())
  125. !! SLICE_ONE_LIST( SELF, $pos, 'k', $k, %other );
  126. }
  127. multi sub postcircumfix:<[ ]>( \SELF, int $pos, :$v!, *%other ) is raw {
  128. $v && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  129. ?? (SELF.EXISTS-POS($pos) ?? nqp::decont(SELF.AT-POS($pos)) !! ())
  130. !! SLICE_ONE_LIST( SELF, $pos, 'v', $v, %other );
  131. }
  132. # @a[Int 1]
  133. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos ) is raw {
  134. SELF.AT-POS($pos);
  135. }
  136. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, Mu \assignee ) is raw {
  137. SELF.ASSIGN-POS($pos, assignee);
  138. }
  139. multi sub postcircumfix:<[ ]>(\SELF, Int:D $pos, Mu :$BIND! is raw) is raw {
  140. SELF.BIND-POS($pos, $BIND);
  141. }
  142. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, :$delete!, *%other ) is raw {
  143. $delete && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  144. ?? SELF.DELETE-POS($pos)
  145. !! SLICE_ONE_LIST( SELF, $pos, 'delete', $delete, %other );
  146. }
  147. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, :$exists!, *%other ) is raw {
  148. $exists && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  149. ?? SELF.EXISTS-POS($pos)
  150. !! SLICE_ONE_LIST( SELF, $pos, 'exists', $exists, %other );
  151. }
  152. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, :$kv!, *%other ) is raw {
  153. $kv && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  154. ?? (SELF.EXISTS-POS($pos) ?? ($pos, SELF.AT-POS($pos)) !! ())
  155. !! SLICE_ONE_LIST( SELF, $pos, 'kv', $kv, %other );
  156. }
  157. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, :$p!, *%other ) is raw {
  158. $p && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  159. ?? (SELF.EXISTS-POS($pos) ?? Pair.new($pos,SELF.AT-POS($pos)) !! ())
  160. !! SLICE_ONE_LIST( SELF, $pos, 'p', $p, %other );
  161. }
  162. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, :$k!, *%other ) is raw {
  163. $k && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  164. ?? (SELF.EXISTS-POS($pos) ?? $pos !! ())
  165. !! SLICE_ONE_LIST( SELF, $pos, 'k', $k, %other );
  166. }
  167. multi sub postcircumfix:<[ ]>( \SELF, Int:D $pos, :$v!, *%other ) is raw {
  168. $v && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  169. ?? (SELF.EXISTS-POS($pos) ?? nqp::decont(SELF.AT-POS($pos)) !! ())
  170. !! SLICE_ONE_LIST( SELF, $pos, 'v', $v, %other );
  171. }
  172. # @a[$x]
  173. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos ) is raw {
  174. SELF.AT-POS(pos.Int);
  175. }
  176. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, Mu \assignee ) is raw {
  177. SELF.ASSIGN-POS(pos.Int, assignee);
  178. }
  179. multi sub postcircumfix:<[ ]>(\SELF, Any:D \pos, Mu :$BIND! is raw) is raw {
  180. SELF.BIND-POS(pos.Int, $BIND);
  181. }
  182. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, :$delete!, *%other ) is raw {
  183. $delete && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  184. ?? SELF.DELETE-POS(pos.Int)
  185. !! SLICE_ONE_LIST( SELF, pos.Int, 'delete', $delete, %other );
  186. }
  187. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, :$exists!, *%other ) is raw {
  188. $exists && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  189. ?? SELF.EXISTS-POS(pos.Int)
  190. !! SLICE_ONE_LIST( SELF, pos.Int, 'exists', $exists, %other );
  191. }
  192. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, :$kv!, *%other ) is raw {
  193. $kv && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  194. ?? (SELF.EXISTS-POS(pos.Int) ?? (pos, SELF.AT-POS(pos.Int)) !! ())
  195. !! SLICE_ONE_LIST( SELF, pos.Int, 'kv', $kv, %other );
  196. }
  197. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, :$p!, *%other ) is raw {
  198. $p && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  199. ?? (SELF.EXISTS-POS(pos.Int) ?? Pair.new(pos, SELF.AT-POS(pos.Int)) !! ())
  200. !! SLICE_ONE_LIST( SELF, pos.Int, 'p', $p, %other );
  201. }
  202. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, :$k!, *%other ) is raw {
  203. $k && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  204. ?? (SELF.EXISTS-POS(pos.Int) ?? pos !! ())
  205. !! SLICE_ONE_LIST( SELF, pos.Int, 'k', $k, %other );
  206. }
  207. multi sub postcircumfix:<[ ]>( \SELF, Any:D \pos, :$v!, *%other ) is raw {
  208. $v && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  209. ?? (SELF.EXISTS-POS(pos.Int) ?? nqp::decont(SELF.AT-POS(pos.Int)) !! ())
  210. !! SLICE_ONE_LIST( SELF, pos.Int, 'v', $v, %other );
  211. }
  212. # @a[@i]
  213. multi sub postcircumfix:<[ ]>( \SELF, Iterable:D \pos ) is raw {
  214. nqp::iscont(pos)
  215. ?? SELF.AT-POS(pos.Int)
  216. !! POSITIONS(SELF, pos).map({ SELF[$_] }).eager.list;
  217. }
  218. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos, Mu \val ) is raw {
  219. # MMD is not behaving itself so we do this by hand.
  220. if nqp::iscont(pos) {
  221. return SELF[pos.Int] = val;
  222. }
  223. # Prep an iterator that will assign Nils past end of rval
  224. my \rvlist :=
  225. do if nqp::iscont(val)
  226. or not nqp::istype(val, Iterator)
  227. and not nqp::istype(val, Iterable) {
  228. (nqp::decont(val),).Slip
  229. }
  230. elsif nqp::istype(val, Iterator) {
  231. Slip.from-loop({ nqp::decont(val.pull-one) })
  232. }
  233. elsif nqp::istype(val, Iterable) {
  234. val.map({ nqp::decont($_) }).Slip
  235. }, (Nil xx Inf).Slip;
  236. if nqp::istype(SELF, Positional) {
  237. # For Positionals, preserve established/expected evaluation order.
  238. my $list := List.new;
  239. my $target := nqp::getattr($list,List,'$!reified');
  240. # We try to reify indices eagerly first, in case doing so
  241. # manipulates SELF. If pos is lazy or contains Whatevers/closures,
  242. # the SELF may start to reify as well.
  243. my \indices := POSITIONS(SELF, pos);
  244. indices.iterator.sink-all;
  245. # Extract the values/containers which will be assigned to, in case
  246. # reifying the rhs does crazy things like splicing SELF.
  247. my int $p = -1;
  248. nqp::bindpos($target,++$p,SELF[$_]) for indices;
  249. rvlist.EXISTS-POS($p);
  250. my \rviter := rvlist.iterator;
  251. $p = -1;
  252. my $elems = nqp::elems($target);
  253. nqp::atpos($target,$p) = rviter.pull-one
  254. while nqp::islt_i(++$p,$elems);
  255. $list
  256. }
  257. else { # The assumption for now is this must be Iterable
  258. # Lazy list assignment. This is somewhat experimental and
  259. # semantics may change.
  260. my $target := SELF.iterator;
  261. my sub eagerize ($idx) {
  262. once $target := $target.cache.iterator;
  263. $idx ~~ Whatever ?? $target.elems !! $target.EXISTS-POS($idx);
  264. }
  265. my @poslist := POSITIONS(SELF, pos, :eagerize(&eagerize)).eager;
  266. my %keep;
  267. # TODO: we could also use a quanthash and count occurences of an
  268. # index to let things go to GC sooner.
  269. %keep{@poslist} = ();
  270. my $max = -1;
  271. my \rviter := rvlist.iterator;
  272. @poslist.map: -> $p {
  273. my $lv;
  274. for $max ^.. $p -> $i {
  275. $max = $i;
  276. my $lv := $target.pull-one;
  277. %keep{$i} := $lv
  278. if %keep{$i}:exists and !($lv =:= IterationEnd);
  279. }
  280. $lv := %keep{$p};
  281. $lv = rviter.pull-one;
  282. };
  283. }
  284. }
  285. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos, :$BIND!) is raw {
  286. X::Bind::Slice.new(type => SELF.WHAT).throw;
  287. }
  288. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos,:$delete!,*%other) is raw {
  289. nqp::iscont(pos)
  290. ?? SLICE_ONE_LIST( SELF, pos.Int, 'delete', $delete, %other )
  291. !! SLICE_MORE_LIST(SELF,POSITIONS(SELF,pos),'delete',$delete,%other)
  292. }
  293. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos,:$exists!,*%other) is raw {
  294. nqp::iscont(pos)
  295. ?? SLICE_ONE_LIST( SELF, pos.Int, 'exists', $exists, %other )
  296. !! SLICE_MORE_LIST(SELF,POSITIONS(SELF,pos),'exists',$exists,%other)
  297. }
  298. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos, :$kv!, *%other) is raw {
  299. nqp::iscont(pos)
  300. ?? SLICE_ONE_LIST( SELF, pos.Int, 'kv', $kv, %other )
  301. !! SLICE_MORE_LIST(SELF,POSITIONS(SELF,pos),'kv',$kv,%other)
  302. }
  303. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos, :$p!, *%other) is raw {
  304. nqp::iscont(pos)
  305. ?? SLICE_ONE_LIST( SELF, pos.Int, 'p', $p, %other )
  306. !! SLICE_MORE_LIST(SELF,POSITIONS(SELF,pos),'p',$p,%other)
  307. }
  308. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos, :$k!, *%other) is raw {
  309. nqp::iscont(pos)
  310. ?? SLICE_ONE_LIST( SELF, pos.Int, 'k', $k, %other )
  311. !! SLICE_MORE_LIST(SELF,POSITIONS(SELF,pos),'k',$k,%other)
  312. }
  313. multi sub postcircumfix:<[ ]>(\SELF, Iterable:D \pos, :$v!, *%other) is raw {
  314. nqp::iscont(pos)
  315. ?? SLICE_ONE_LIST( SELF, pos.Int, 'v', $v, %other )
  316. !! SLICE_MORE_LIST(SELF,POSITIONS(SELF,pos),'v',$v,%other)
  317. }
  318. # @a[->{}]
  319. multi sub postcircumfix:<[ ]>(\SELF, Callable:D $block ) is raw {
  320. nqp::stmts(
  321. (my $*INDEX = 'Effective index'),
  322. SELF[$block.pos(SELF)]
  323. )
  324. }
  325. multi sub postcircumfix:<[ ]>(\SELF, Callable:D $block, Mu \assignee ) is raw {
  326. nqp::stmts(
  327. (my $*INDEX = 'Effective index'),
  328. SELF[$block.pos(SELF)] = assignee
  329. )
  330. }
  331. multi sub postcircumfix:<[ ]>(\SELF, Callable:D $block, :$BIND!) is raw {
  332. X::Bind::Slice.new(type => SELF.WHAT).throw;
  333. }
  334. multi sub postcircumfix:<[ ]>(\SELF,Callable:D $block,:$delete!,*%other) is raw {
  335. nqp::stmts(
  336. (my $*INDEX = 'Effective index'),
  337. nqp::if(
  338. nqp::istype((my $pos := $block.pos(SELF)),Int),
  339. SLICE_ONE_LIST( SELF, $pos, 'delete', $delete, %other ),
  340. SLICE_MORE_LIST( SELF, @$pos, 'delete', $delete, %other )
  341. )
  342. )
  343. }
  344. multi sub postcircumfix:<[ ]>(\SELF,Callable:D $block,:$exists!,*%other) is raw {
  345. nqp::stmts(
  346. (my $*INDEX = 'Effective index'),
  347. nqp::if(
  348. nqp::istype((my $pos := $block.pos(SELF)),Int),
  349. SLICE_ONE_LIST( SELF, $pos, 'exists', $exists, %other ),
  350. SLICE_MORE_LIST( SELF, @$pos, 'exists', $exists, %other )
  351. )
  352. )
  353. }
  354. multi sub postcircumfix:<[ ]>(\SELF,Callable:D $block,:$kv!,*%other) is raw {
  355. nqp::stmts(
  356. (my $*INDEX = 'Effective index'),
  357. nqp::if(
  358. nqp::istype((my $pos := $block.pos(SELF)),Int),
  359. SLICE_ONE_LIST( SELF, $pos, 'kv', $kv, %other ),
  360. SLICE_MORE_LIST( SELF, @$pos, 'kv', $kv, %other )
  361. )
  362. )
  363. }
  364. multi sub postcircumfix:<[ ]>(\SELF,Callable:D $block,:$p!,*%other) is raw {
  365. nqp::stmts(
  366. (my $*INDEX = 'Effective index'),
  367. nqp::if(
  368. nqp::istype((my $pos := $block.pos(SELF)),Int),
  369. SLICE_ONE_LIST( SELF, $pos, 'p', $p, %other ),
  370. SLICE_MORE_LIST( SELF, @$pos, 'p', $p, %other )
  371. )
  372. )
  373. }
  374. multi sub postcircumfix:<[ ]>(\SELF,Callable:D $block,:$k!,*%other) is raw {
  375. nqp::stmts(
  376. (my $*INDEX = 'Effective index'),
  377. nqp::if(
  378. nqp::istype((my $pos := $block.pos(SELF)),Int),
  379. SLICE_ONE_LIST( SELF, $pos, 'k', $k, %other ),
  380. SLICE_MORE_LIST( SELF, @$pos, 'k', $k, %other )
  381. )
  382. )
  383. }
  384. multi sub postcircumfix:<[ ]>(\SELF,Callable:D $block,:$v!,*%other) is raw {
  385. nqp::stmts(
  386. (my $*INDEX = 'Effective index'),
  387. nqp::if(
  388. nqp::istype((my $pos := $block.pos(SELF)),Int),
  389. SLICE_ONE_LIST( SELF, $pos, 'v', $v, %other ),
  390. SLICE_MORE_LIST( SELF, @$pos, 'v', $v, %other )
  391. )
  392. )
  393. }
  394. # @a[*]
  395. multi sub postcircumfix:<[ ]>( \SELF, Whatever:D ) is raw {
  396. SELF[^SELF.elems];
  397. }
  398. multi sub postcircumfix:<[ ]>( \SELF, Whatever:D, Mu \assignee ) is raw {
  399. SELF[^SELF.elems] = assignee;
  400. }
  401. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$BIND!) is raw {
  402. X::Bind::Slice.new(type => SELF.WHAT).throw;
  403. }
  404. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$delete!, *%other) is raw {
  405. SLICE_MORE_LIST( SELF, ^SELF.elems, 'delete', $delete, %other );
  406. }
  407. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$exists!, *%other) is raw {
  408. SLICE_MORE_LIST( SELF, ^SELF.elems, 'exists', $exists, %other );
  409. }
  410. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$kv!, *%other) is raw {
  411. SLICE_MORE_LIST( SELF, ^SELF.elems, 'kv', $kv, %other );
  412. }
  413. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$p!, *%other) is raw {
  414. SLICE_MORE_LIST( SELF, ^SELF.elems, 'p', $p, %other );
  415. }
  416. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$k!, *%other) is raw {
  417. SLICE_MORE_LIST( SELF, ^SELF.elems, 'k', $k, %other );
  418. }
  419. multi sub postcircumfix:<[ ]>(\SELF, Whatever:D, :$v!, *%other) is raw {
  420. nqp::elems(nqp::getattr(%other,Map,'$!storage'))
  421. ?? SLICE_MORE_LIST( SELF, ^SELF.elems, 'v', $v, %other )
  422. !! SELF[^SELF.elems];
  423. }
  424. # @a[**]
  425. multi sub postcircumfix:<[ ]>(\SELF, HyperWhatever:D $, *%adv) is raw {
  426. X::NYI.new(feature => 'HyperWhatever in array index').throw;
  427. }
  428. multi sub postcircumfix:<[ ]>(\SELF, HyperWhatever:D $, Mu \assignee) is raw {
  429. X::NYI.new(feature => 'HyperWhatever in array index').throw;
  430. }
  431. # @a[]
  432. multi sub postcircumfix:<[ ]>(\SELF, :$BIND!) is raw {
  433. X::Bind::ZenSlice.new(type => SELF.WHAT).throw;
  434. }
  435. multi sub postcircumfix:<[ ]>(\SELF, :$delete!, *%other) is raw {
  436. SLICE_MORE_LIST( SELF, ^SELF.elems, 'delete', $delete, %other );
  437. }
  438. multi sub postcircumfix:<[ ]>(\SELF, :$exists!, *%other) is raw {
  439. SLICE_MORE_LIST( SELF, ^SELF.elems, 'exists', $exists, %other );
  440. }
  441. multi sub postcircumfix:<[ ]>(\SELF, :$kv!, *%other) is raw {
  442. SLICE_MORE_LIST( SELF, ^SELF.elems, 'kv', $kv, %other );
  443. }
  444. multi sub postcircumfix:<[ ]>(\SELF, :$p!, *%other) is raw {
  445. SLICE_MORE_LIST( SELF, ^SELF.elems, 'p', $p, %other );
  446. }
  447. multi sub postcircumfix:<[ ]>(\SELF, :$k!, *%other) is raw {
  448. SLICE_MORE_LIST( SELF, ^SELF.elems, 'k', $k, %other );
  449. }
  450. multi sub postcircumfix:<[ ]>(\SELF, :$v!, *%other) is raw {
  451. nqp::elems(nqp::getattr(%other,Map,'$!storage'))
  452. ?? SLICE_MORE_LIST( SELF, ^SELF.elems, 'v', $v, %other )
  453. !! SELF[^SELF.elems];
  454. }
  455. multi sub postcircumfix:<[ ]>(\SELF, *%other) is raw {
  456. SELF.ZEN-POS(|%other);
  457. }