1. # all sub postcircumfix {} candidates here please
  2. proto sub postcircumfix:<{ }>(|) is nodal { * }
  3. # %h<key>
  4. multi sub postcircumfix:<{ }>( \SELF, \key ) is raw {
  5. SELF.AT-KEY(key);
  6. }
  7. multi sub postcircumfix:<{ }>(\SELF, \key, Mu \ASSIGN) is raw {
  8. SELF.ASSIGN-KEY(key, ASSIGN);
  9. }
  10. multi sub postcircumfix:<{ }>(\SELF, \key, Mu :$BIND! is raw) is raw {
  11. SELF.BIND-KEY(key, $BIND);
  12. }
  13. multi sub postcircumfix:<{ }>( \SELF, \key, :$delete!, *%other ) is raw {
  14. nqp::if(
  15. $delete && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage'))),
  16. SELF.DELETE-KEY(key),
  17. SLICE_ONE_HASH( SELF, key, 'delete', $delete, %other )
  18. )
  19. }
  20. multi sub postcircumfix:<{ }>( \SELF, \key, :$exists!, *%other ) is raw {
  21. nqp::if(
  22. $exists && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage'))),
  23. SELF.EXISTS-KEY(key),
  24. SLICE_ONE_HASH( SELF, key, 'exists', $exists, %other )
  25. )
  26. }
  27. multi sub postcircumfix:<{ }>( \SELF, \key, :$kv!, *%other ) is raw {
  28. $kv && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  29. ?? (SELF.EXISTS-KEY(key) ?? (key,SELF.AT-KEY(key)) !! ())
  30. !! SLICE_ONE_HASH( SELF, key, 'kv', $kv, %other );
  31. }
  32. multi sub postcircumfix:<{ }>( \SELF, \key, :$p!, *%other ) is raw {
  33. $p && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  34. ?? (SELF.EXISTS-KEY(key) ?? Pair.new(key,SELF.AT-KEY(key)) !! ())
  35. !! SLICE_ONE_HASH( SELF, key, 'p', $p, %other );
  36. }
  37. multi sub postcircumfix:<{ }>( \SELF, \key, :$k!, *%other ) is raw {
  38. $k && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  39. ?? (SELF.EXISTS-KEY(key) ?? key !! ())
  40. !! SLICE_ONE_HASH( SELF, key, 'k', $k, %other );
  41. }
  42. multi sub postcircumfix:<{ }>( \SELF, \key, :$v!, *%other ) is raw {
  43. $v && nqp::not_i(nqp::elems(nqp::getattr(%other,Map,'$!storage')))
  44. ?? (SELF.EXISTS-KEY(key) ?? nqp::decont(SELF.AT-KEY(key)) !! ())
  45. !! SLICE_ONE_HASH( SELF, key, 'v', $v, %other );
  46. }
  47. # %h<a b c>
  48. multi sub postcircumfix:<{ }>( \SELF, Iterable \key ) is raw {
  49. nqp::iscont(key)
  50. ?? SELF.AT-KEY(key)
  51. !! key.flatmap({ SELF{$_} }).eager.list;
  52. }
  53. multi sub postcircumfix:<{ }>(\SELF, Iterable \key, Mu \ASSIGN) is raw {
  54. nqp::iscont(key)
  55. ?? SELF.ASSIGN-KEY(key, ASSIGN)
  56. !! (key.flatmap({ SELF{$_} }).eager.list = ASSIGN)
  57. }
  58. multi sub postcircumfix:<{ }>(\SELF, Iterable \key, :$BIND!) is raw {
  59. X::Bind::Slice.new(type => SELF.WHAT).throw;
  60. }
  61. multi sub postcircumfix:<{ }>(\SELF,Iterable \key, :$delete!,*%other) is raw {
  62. nqp::iscont(key)
  63. ?? SLICE_ONE_HASH( SELF, key, 'delete', $delete, %other )
  64. !! SLICE_MORE_HASH( SELF, key, 'delete', $delete, %other )
  65. }
  66. multi sub postcircumfix:<{ }>(\SELF,Iterable \key, :$exists!,*%other) is raw {
  67. nqp::iscont(key)
  68. ?? SLICE_ONE_HASH( SELF, key, 'exists', $exists, %other )
  69. !! SLICE_MORE_HASH( SELF, key, 'exists', $exists, %other )
  70. }
  71. multi sub postcircumfix:<{ }>(\SELF, Iterable \key, :$kv!, *%other) is raw {
  72. nqp::iscont(key)
  73. ?? SLICE_ONE_HASH( SELF, key, 'kv', $kv, %other )
  74. !! SLICE_MORE_HASH( SELF, key, 'kv', $kv, %other )
  75. }
  76. multi sub postcircumfix:<{ }>(\SELF, Iterable \key, :$p!, *%other) is raw {
  77. nqp::iscont(key)
  78. ?? SLICE_ONE_HASH( SELF, key, 'p', $p, %other )
  79. !! SLICE_MORE_HASH( SELF, key, 'p', $p, %other )
  80. }
  81. multi sub postcircumfix:<{ }>(\SELF, Iterable \key, :$k!, *%other) is raw {
  82. nqp::iscont(key)
  83. ?? SLICE_ONE_HASH( SELF, key, 'k', $k, %other )
  84. !! SLICE_MORE_HASH( SELF, key, 'k', $k, %other )
  85. }
  86. multi sub postcircumfix:<{ }>(\SELF, Iterable \key, :$v!, *%other) is raw {
  87. nqp::iscont(key)
  88. ?? SLICE_ONE_HASH( SELF, key, 'v', $v, %other )
  89. !! SLICE_MORE_HASH( SELF, key, 'v', $v, %other )
  90. }
  91. # %h{*}
  92. multi sub postcircumfix:<{ }>( \SELF, Whatever ) is raw {
  93. SELF{SELF.keys.list};
  94. }
  95. multi sub postcircumfix:<{ }>(\SELF, Whatever, Mu \ASSIGN) is raw {
  96. die "Cannot assign to *, as the order of keys is non-deterministic";
  97. }
  98. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$BIND!) is raw {
  99. X::Bind::Slice.new(type => SELF.WHAT).throw;
  100. }
  101. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$delete!, *%other) is raw {
  102. SLICE_MORE_HASH( SELF, SELF.keys.list, 'delete', $delete, %other );
  103. }
  104. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$exists!, *%other) is raw {
  105. SLICE_MORE_HASH( SELF, SELF.keys.list, 'exists', $exists, %other );
  106. }
  107. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$kv!, *%other) is raw {
  108. SLICE_MORE_HASH( SELF, SELF.keys.list, 'kv', $kv, %other );
  109. }
  110. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$p!, *%other) is raw {
  111. SLICE_MORE_HASH( SELF, SELF.keys.list, 'p', $p, %other );
  112. }
  113. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$k!, *%other) is raw {
  114. SLICE_MORE_HASH( SELF, SELF.keys.list, 'k', $k, %other );
  115. }
  116. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$p!, *%other) is raw {
  117. SLICE_MORE_HASH( SELF, SELF.keys.list, 'p', $p, %other );
  118. }
  119. multi sub postcircumfix:<{ }>(\SELF, Whatever, :$v!, *%other) is raw {
  120. nqp::elems(nqp::getattr(%other,Map,'$!storage'))
  121. ?? SLICE_MORE_HASH( SELF, SELF.keys.list, 'v', $v, %other )
  122. !! SELF{SELF.keys.list};
  123. }
  124. # %h{}
  125. multi sub postcircumfix:<{ }>(\SELF, :$BIND!) is raw {
  126. X::Bind::ZenSlice.new(type => SELF.WHAT).throw;
  127. }
  128. multi sub postcircumfix:<{ }>(\SELF, :$delete!, *%other) is raw {
  129. SLICE_MORE_HASH( SELF, SELF.keys.list, 'delete', $delete, %other );
  130. }
  131. multi sub postcircumfix:<{ }>(\SELF, :$exists!, *%other) is raw {
  132. SLICE_MORE_HASH( SELF, SELF.keys.list, 'exists', $exists, %other );
  133. }
  134. multi sub postcircumfix:<{ }>(\SELF, :$kv!, *%other) is raw {
  135. SLICE_MORE_HASH( SELF, SELF.keys.list, 'kv', $kv, %other );
  136. }
  137. multi sub postcircumfix:<{ }>(\SELF, :$p!, *%other) is raw {
  138. SLICE_MORE_HASH( SELF, SELF.keys.list, 'p', $p, %other );
  139. }
  140. multi sub postcircumfix:<{ }>(\SELF, :$k!, *%other) is raw {
  141. SLICE_MORE_HASH( SELF, SELF.keys.list, 'k', $k, %other );
  142. }
  143. multi sub postcircumfix:<{ }>(\SELF, :$p!, *%other) is raw {
  144. SLICE_MORE_HASH( SELF, SELF.keys.list, 'p', $p, %other );
  145. }
  146. multi sub postcircumfix:<{ }>(\SELF, :$v!, *%other) is raw {
  147. nqp::elems(nqp::getattr(%other,Map,'$!storage'))
  148. ?? SLICE_MORE_HASH( SELF, SELF.keys.list, 'v', $v, %other )
  149. !! SELF{SELF.keys.list};
  150. }
  151. multi sub postcircumfix:<{ }>( \SELF, *%other ) is raw {
  152. SELF.ZEN-KEY(|%other);
  153. }
  154. proto sub postcircumfix:<{; }>(|) is nodal { * }
  155. sub MD-HASH-SLICE-ONE-POSITION(\SELF, \indices, \idx, int $dim, \target) {
  156. my int $next-dim = $dim + 1;
  157. if $next-dim < indices.elems {
  158. if nqp::istype(idx, Iterable) && !nqp::iscont(idx) {
  159. for idx {
  160. MD-HASH-SLICE-ONE-POSITION(SELF, indices, $_, $dim, target)
  161. }
  162. }
  163. elsif nqp::istype(idx, Str) {
  164. MD-HASH-SLICE-ONE-POSITION(SELF.AT-KEY(idx), indices, indices.AT-POS($next-dim), $next-dim, target)
  165. }
  166. elsif nqp::istype(idx, Whatever) {
  167. for SELF.keys {
  168. MD-HASH-SLICE-ONE-POSITION(SELF.AT-KEY($_), indices, indices.AT-POS($next-dim), $next-dim, target)
  169. }
  170. }
  171. else {
  172. MD-HASH-SLICE-ONE-POSITION(SELF.AT-KEY(idx), indices, indices.AT-POS($next-dim), $next-dim, target)
  173. }
  174. }
  175. else {
  176. if nqp::istype(idx, Iterable) && !nqp::iscont(idx) {
  177. for idx {
  178. MD-HASH-SLICE-ONE-POSITION(SELF, indices, $_, $dim, target)
  179. }
  180. }
  181. elsif nqp::istype(idx, Str) {
  182. nqp::push(target, SELF.AT-KEY(idx))
  183. }
  184. elsif nqp::istype(idx, Whatever) {
  185. for SELF.keys {
  186. nqp::push(target, SELF.AT-KEY($_))
  187. }
  188. }
  189. else {
  190. nqp::push(target, SELF.AT-KEY(idx))
  191. }
  192. }
  193. }
  194. multi sub postcircumfix:<{; }>(\SELF, @indices) {
  195. my \target = IterationBuffer.new;
  196. MD-HASH-SLICE-ONE-POSITION(SELF, @indices, @indices.AT-POS(0), 0, target);
  197. nqp::p6bindattrinvres(nqp::create(List), List, '$!reified', target)
  198. }
  199. multi sub postcircumfix:<{; }>(\SELF, @indices, :$exists!) {
  200. sub recurse-at-key(\SELF, \indices) {
  201. my \idx := indices[0];
  202. my \exists := SELF.EXISTS-KEY(idx);
  203. nqp::if(
  204. nqp::istype(idx, Iterable),
  205. idx.map({ |recurse-at-key(SELF, ($_, |indices.skip.cache)) }).List,
  206. nqp::if(
  207. nqp::iseq_I(indices.elems, 1),
  208. exists,
  209. nqp::if(
  210. exists,
  211. recurse-at-key(SELF{idx}, indices.skip.cache),
  212. nqp::stmts(
  213. (my \times := indices.map({ .elems }).reduce(&[*])),
  214. nqp::if(
  215. nqp::iseq_I(times, 1),
  216. False,
  217. (False xx times).List
  218. )
  219. ).head
  220. )
  221. )
  222. );
  223. }
  224. recurse-at-key(SELF, @indices)
  225. }