1. my class X::MustBeParametric { ... }
  2. my class X::TooManyDimensions { ... }
  3. my class X::TypeCheck::Assignment { ... }
  4. my class array does Iterable {
  5. multi method new(array:) { self!create }
  6. multi method new(array: @v) { self!create.STORE(@v) }
  7. multi method new(array: **@v) { self!create.STORE(@v) }
  8. multi method new(array: :$shape!) { self!create-ws($shape) }
  9. multi method new(array: @v, :$shape!) { self!create-ws($shape).STORE(@v) }
  10. multi method new(array: **@v, :$shape!) { self!create-ws($shape).STORE(@v) }
  11. method !create() {
  12. nqp::isnull(nqp::typeparameterized(self))
  13. ?? X::MustBeParametric.new(:type(self)).throw
  14. !! nqp::create(self)
  15. }
  16. method !create-ws($shape) {
  17. nqp::isnull(nqp::typeparameterized(self))
  18. ?? X::MustBeParametric.new(:type(self)).throw
  19. !! nqp::isconcrete($shape)
  20. ?? self!shaped($shape)
  21. !! Metamodel::EnumHOW.ACCEPTS($shape.HOW)
  22. ?? self!shaped($shape.^elems)
  23. !! nqp::create(self)
  24. }
  25. proto method STORE(|) { * }
  26. multi method STORE(array:D: *@values) { self.STORE(@values) }
  27. multi method push(array:D: **@values) { self.append(@values) }
  28. multi method append(array:D: *@values) { self.append(@values) }
  29. multi method unshift(array:D: **@values) { self.unshift(@values) }
  30. multi method prepend(array:D: *@values) { self.unshift(@values) }
  31. sub EQV_DIMENSIONS(Mu \one, Mu \two) is raw {
  32. nqp::iseq_i( # much faster than one.shape eqv two.shape
  33. (my int $dims = nqp::elems(
  34. my $onedims := nqp::dimensions(one)
  35. )),
  36. nqp::elems(my $twodims := nqp::dimensions(two))
  37. ) && nqp::stmts(
  38. (my int $i = -1),
  39. nqp::while(
  40. nqp::islt_i(($i = nqp::add_i($i,1)),$dims)
  41. && nqp::iseq_i(
  42. nqp::atpos_i($onedims,$i),
  43. nqp::atpos_i($twodims,$i)
  44. ),
  45. nqp::null
  46. ),
  47. nqp::iseq_i($i,$dims)
  48. )
  49. }
  50. my role strarray[::T] does Positional[T] is array_type(T) {
  51. #- start of generated part of strarray role -----------------------------------
  52. #- Generated on 2017-03-15T11:21:04+01:00 by tools/build/makeNATIVE_ARRAY.pl6
  53. #- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
  54. multi method AT-POS(strarray:D: int $idx) is raw {
  55. nqp::atposref_s(self, $idx)
  56. }
  57. multi method AT-POS(strarray:D: Int:D $idx) is raw {
  58. nqp::atposref_s(self, $idx)
  59. }
  60. multi method ASSIGN-POS(strarray:D: int $idx, str $value) {
  61. nqp::bindpos_s(self, $idx, $value)
  62. }
  63. multi method ASSIGN-POS(strarray:D: Int:D $idx, str $value) {
  64. nqp::bindpos_s(self, $idx, $value)
  65. }
  66. multi method ASSIGN-POS(strarray:D: int $idx, Str:D $value) {
  67. nqp::bindpos_s(self, $idx, $value)
  68. }
  69. multi method ASSIGN-POS(strarray:D: Int:D $idx, Str:D $value) {
  70. nqp::bindpos_s(self, $idx, $value)
  71. }
  72. multi method ASSIGN-POS(strarray:D: Any $idx, Mu \value) {
  73. X::TypeCheck.new(
  74. operation => "assignment to str array element #$idx",
  75. got => value,
  76. expected => T,
  77. ).throw;
  78. }
  79. multi method STORE(strarray:D: $value) {
  80. nqp::bindpos_s(self, 0, nqp::unbox_s($value));
  81. self
  82. }
  83. multi method STORE(strarray:D: str @values) {
  84. nqp::splice(self,@values,0,0)
  85. }
  86. multi method STORE(strarray:D: @values) {
  87. my int $elems = @values.elems;
  88. nqp::setelems(self, $elems);
  89. my int $i = -1;
  90. nqp::bindpos_s(self, $i,
  91. nqp::unbox_s(@values.AT-POS($i)))
  92. while nqp::islt_i($i = nqp::add_i($i,1),$elems);
  93. self
  94. }
  95. multi method push(strarray:D: str $value) {
  96. nqp::push_s(self, $value);
  97. self
  98. }
  99. multi method push(strarray:D: Str:D $value) {
  100. nqp::push_s(self, $value);
  101. self
  102. }
  103. multi method push(strarray:D: Mu \value) {
  104. X::TypeCheck.new(
  105. operation => 'push to str array',
  106. got => value,
  107. expected => T,
  108. ).throw;
  109. }
  110. multi method append(strarray:D: str $value) {
  111. nqp::push_s(self, $value);
  112. self
  113. }
  114. multi method append(strarray:D: Str:D $value) {
  115. nqp::push_s(self, $value);
  116. self
  117. }
  118. multi method append(strarray:D: str @values) {
  119. nqp::splice(self,@values,nqp::elems(self),0)
  120. }
  121. multi method append(strarray:D: @values) {
  122. fail X::Cannot::Lazy.new(:action<append>, :what(self.^name))
  123. if @values.is-lazy;
  124. nqp::push_s(self, $_) for flat @values;
  125. self
  126. }
  127. method pop(strarray:D: --> str) {
  128. nqp::elems(self) > 0
  129. ?? nqp::pop_s(self)
  130. !! die X::Cannot::Empty.new(:action<pop>, :what(self.^name));
  131. }
  132. method shift(strarray:D: --> str) {
  133. nqp::elems(self) > 0
  134. ?? nqp::shift_s(self)
  135. !! die X::Cannot::Empty.new(:action<shift>, :what(self.^name));
  136. }
  137. multi method unshift(strarray:D: str $value) {
  138. nqp::unshift_s(self, $value);
  139. self
  140. }
  141. multi method unshift(strarray:D: Str:D $value) {
  142. nqp::unshift_s(self, $value);
  143. self
  144. }
  145. multi method unshift(strarray:D: @values) {
  146. fail X::Cannot::Lazy.new(:action<unshift>, :what(self.^name))
  147. if @values.is-lazy;
  148. nqp::unshift_s(self, @values.pop) while @values;
  149. self
  150. }
  151. multi method unshift(strarray:D: Mu \value) {
  152. X::TypeCheck.new(
  153. operation => 'unshift to str array',
  154. got => value,
  155. expected => T,
  156. ).throw;
  157. }
  158. multi method splice(strarray:D: $offset=0, $size=Whatever, *@values) {
  159. fail X::Cannot::Lazy.new(:action('splice in'))
  160. if @values.is-lazy;
  161. my $elems = self.elems;
  162. my int $o = nqp::istype($offset,Callable)
  163. ?? $offset($elems)
  164. !! nqp::istype($offset,Whatever)
  165. ?? $elems
  166. !! $offset.Int;
  167. X::OutOfRange.new(
  168. :what('Offset argument to splice'),
  169. :got($o),
  170. :range("0..$elems"),
  171. ).fail if $o < 0 || $o > $elems; # one after list allowed for "push"
  172. my int $s = nqp::istype($size,Callable)
  173. ?? $size($elems - $o)
  174. !! !defined($size) || nqp::istype($size,Whatever)
  175. ?? $elems - ($o min $elems)
  176. !! $size.Int;
  177. X::OutOfRange.new(
  178. :what('Size argument to splice'),
  179. :got($s),
  180. :range("0..^{$elems - $o}"),
  181. ).fail if $s < 0;
  182. my @ret := nqp::create(self);
  183. my int $i = $o;
  184. my int $n = ($elems min $o + $s) - 1;
  185. while $i <= $n {
  186. nqp::push_s(@ret, nqp::atpos_s(self, $i));
  187. $i = $i + 1;
  188. }
  189. my @splicees := nqp::create(self);
  190. nqp::push_s(@splicees, @values.shift) while @values;
  191. nqp::splice(self, @splicees, $o, $s);
  192. @ret;
  193. }
  194. multi method min(strarray:D:) {
  195. nqp::if(
  196. (my int $elems = self.elems),
  197. nqp::stmts(
  198. (my int $i),
  199. (my str $min = nqp::atpos_s(self,0)),
  200. nqp::while(
  201. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  202. nqp::if(
  203. nqp::islt_s(nqp::atpos_s(self,$i),$min),
  204. ($min = nqp::atpos_s(self,$i))
  205. )
  206. ),
  207. $min
  208. ),
  209. Inf
  210. )
  211. }
  212. multi method max(strarray:D:) {
  213. nqp::if(
  214. (my int $elems = self.elems),
  215. nqp::stmts(
  216. (my int $i),
  217. (my str $max = nqp::atpos_s(self,0)),
  218. nqp::while(
  219. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  220. nqp::if(
  221. nqp::isgt_s(nqp::atpos_s(self,$i),$max),
  222. ($max = nqp::atpos_s(self,$i))
  223. )
  224. ),
  225. $max
  226. ),
  227. -Inf
  228. )
  229. }
  230. multi method minmax(strarray:D:) {
  231. nqp::if(
  232. (my int $elems = self.elems),
  233. nqp::stmts(
  234. (my int $i),
  235. (my str $min =
  236. my str $max = nqp::atpos_s(self,0)),
  237. nqp::while(
  238. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  239. nqp::if(
  240. nqp::islt_s(nqp::atpos_s(self,$i),$min),
  241. ($min = nqp::atpos_s(self,$i)),
  242. nqp::if(
  243. nqp::isgt_s(nqp::atpos_s(self,$i),$max),
  244. ($max = nqp::atpos_s(self,$i))
  245. )
  246. )
  247. ),
  248. Range.new($min,$max)
  249. ),
  250. Range.new(Inf,-Inf)
  251. )
  252. }
  253. method iterator(strarray:D:) {
  254. class :: does Iterator {
  255. has int $!i;
  256. has $!array; # Native array we're iterating
  257. method !SET-SELF(\array) {
  258. $!array := nqp::decont(array);
  259. $!i = -1;
  260. self
  261. }
  262. method new(\array) { nqp::create(self)!SET-SELF(array) }
  263. method pull-one() is raw {
  264. ($!i = $!i + 1) < nqp::elems($!array)
  265. ?? nqp::atposref_s($!array,$!i)
  266. !! IterationEnd
  267. }
  268. method push-all($target --> IterationEnd) {
  269. my int $i = $!i;
  270. my int $elems = nqp::elems($!array);
  271. $target.push(nqp::atposref_s($!array,$i))
  272. while ($i = $i + 1) < $elems;
  273. $!i = $i;
  274. }
  275. }.new(self)
  276. }
  277. method reverse(strarray:D:) is nodal {
  278. nqp::stmts(
  279. (my int $elems = nqp::elems(self)),
  280. (my int $last = nqp::sub_i($elems,1)),
  281. (my int $i = -1),
  282. (my $to := nqp::clone(self)),
  283. nqp::while(
  284. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  285. nqp::bindpos_s($to,nqp::sub_i($last,$i),
  286. nqp::atpos_s(self,$i))
  287. ),
  288. $to
  289. )
  290. }
  291. method rotate(strarray:D: Int(Cool) $rotate = 1) is nodal {
  292. nqp::stmts(
  293. (my int $elems = nqp::elems(self)),
  294. (my $to := nqp::clone(self)),
  295. (my int $i = -1),
  296. (my int $j =
  297. nqp::mod_i(nqp::sub_i(nqp::sub_i($elems,1),$rotate),$elems)),
  298. nqp::if(nqp::islt_i($j,0),($j = nqp::add_i($j,$elems))),
  299. nqp::while(
  300. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  301. nqp::bindpos_s(
  302. $to,
  303. ($j = nqp::mod_i(nqp::add_i($j,1),$elems)),
  304. nqp::atpos_s(self,$i)
  305. ),
  306. ),
  307. $to
  308. )
  309. }
  310. # https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation
  311. multi method sort(strarray:D:) {
  312. nqp::if(
  313. nqp::isgt_i((my int $n = nqp::elems(self)),2),
  314. # $A has the items to sort; $B is a work array
  315. nqp::stmts(
  316. (my Mu $A := nqp::clone(self)),
  317. (my Mu $B := nqp::setelems(nqp::create(self),$n)),
  318. # Each 1-element run in $A is already "sorted"
  319. # Make successively longer sorted runs of length 2, 4, 8, 16...
  320. # until $A is wholly sorted
  321. (my int $width = 1),
  322. nqp::while(
  323. nqp::islt_i($width,$n),
  324. nqp::stmts(
  325. (my int $l = 0),
  326. # $A is full of runs of length $width
  327. nqp::while(
  328. nqp::islt_i($l,$n),
  329. nqp::stmts(
  330. (my int $left = $l),
  331. (my int $right = nqp::add_i($l,$width)),
  332. nqp::if(nqp::isge_i($right,$n),($right = $n)),
  333. (my int $end =
  334. nqp::add_i($l,nqp::add_i($width,$width))),
  335. nqp::if(nqp::isge_i($end,$n),($end = $n)),
  336. (my int $i = $left),
  337. (my int $j = $right),
  338. (my int $k = nqp::sub_i($left,1)),
  339. # Merge two runs: $A[i .. i+width-1] and
  340. # $A[i+width .. i+2*width-1]
  341. # to $B or copy $A[i..n-1] to $B[] ( if(i+width >= n) )
  342. nqp::while(
  343. nqp::islt_i(($k = nqp::add_i($k,1)),$end),
  344. nqp::if(
  345. nqp::islt_i($i,$right) && (
  346. nqp::isge_i($j,$end)
  347. || nqp::islt_s(
  348. nqp::atpos_s($A,$i),
  349. nqp::atpos_s($A,$j)
  350. )
  351. ),
  352. nqp::stmts(
  353. (nqp::bindpos_s($B,$k,nqp::atpos_s($A,$i))),
  354. ($i = nqp::add_i($i,1))
  355. ),
  356. nqp::stmts(
  357. (nqp::bindpos_s($B,$k,nqp::atpos_s($A,$j))),
  358. ($j = nqp::add_i($j,1))
  359. )
  360. )
  361. ),
  362. ($l = nqp::add_i($l,nqp::add_i($width,$width)))
  363. )
  364. ),
  365. # Now work array $B is full of runs of length 2*width.
  366. # Copy array B to array A for next iteration. A more
  367. # efficient implementation would swap the roles of A and B.
  368. (my Mu $temp := $B),($B := $A),($A := $temp), # swap
  369. # Now array $A is full of runs of length 2*width.
  370. ($width = nqp::add_i($width,$width))
  371. )
  372. ),
  373. $A
  374. ),
  375. nqp::if(
  376. nqp::islt_i($n,2)
  377. || nqp::isle_s(nqp::atpos_s(self,0),nqp::atpos_s(self,1)),
  378. nqp::clone(self), # we already have the result
  379. nqp::stmts(
  380. (my $R := nqp::setelems(nqp::create(self),2)),
  381. nqp::bindpos_s($R,0,nqp::atpos_s(self,1)),
  382. nqp::bindpos_s($R,1,nqp::atpos_s(self,0)),
  383. $R
  384. )
  385. )
  386. )
  387. }
  388. #- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
  389. #- end of generated part of strarray role -------------------------------------
  390. method join(strarray:D: $delim = '') {
  391. my str $empty = "";
  392. my int $elems = nqp::elems(self);
  393. my int $i = -1;
  394. nqp::bindpos_s(self,$i,$empty)
  395. if nqp::isnull_s(nqp::atposref_s(self,$i))
  396. while nqp::islt_i(++$i,$elems);
  397. nqp::join($delim.Str,self)
  398. }
  399. }
  400. my role intarray[::T] does Positional[T] is array_type(T) {
  401. #- start of generated part of intarray role -----------------------------------
  402. #- Generated on 2017-03-15T11:21:04+01:00 by tools/build/makeNATIVE_ARRAY.pl6
  403. #- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
  404. multi method AT-POS(intarray:D: int $idx) is raw {
  405. nqp::atposref_i(self, $idx)
  406. }
  407. multi method AT-POS(intarray:D: Int:D $idx) is raw {
  408. nqp::atposref_i(self, $idx)
  409. }
  410. multi method ASSIGN-POS(intarray:D: int $idx, int $value) {
  411. nqp::bindpos_i(self, $idx, $value)
  412. }
  413. multi method ASSIGN-POS(intarray:D: Int:D $idx, int $value) {
  414. nqp::bindpos_i(self, $idx, $value)
  415. }
  416. multi method ASSIGN-POS(intarray:D: int $idx, Int:D $value) {
  417. nqp::bindpos_i(self, $idx, $value)
  418. }
  419. multi method ASSIGN-POS(intarray:D: Int:D $idx, Int:D $value) {
  420. nqp::bindpos_i(self, $idx, $value)
  421. }
  422. multi method ASSIGN-POS(intarray:D: Any $idx, Mu \value) {
  423. X::TypeCheck.new(
  424. operation => "assignment to int array element #$idx",
  425. got => value,
  426. expected => T,
  427. ).throw;
  428. }
  429. multi method STORE(intarray:D: $value) {
  430. nqp::bindpos_i(self, 0, nqp::unbox_i($value));
  431. self
  432. }
  433. multi method STORE(intarray:D: int @values) {
  434. nqp::splice(self,@values,0,0)
  435. }
  436. multi method STORE(intarray:D: @values) {
  437. my int $elems = @values.elems;
  438. nqp::setelems(self, $elems);
  439. my int $i = -1;
  440. nqp::bindpos_i(self, $i,
  441. nqp::unbox_i(@values.AT-POS($i)))
  442. while nqp::islt_i($i = nqp::add_i($i,1),$elems);
  443. self
  444. }
  445. multi method push(intarray:D: int $value) {
  446. nqp::push_i(self, $value);
  447. self
  448. }
  449. multi method push(intarray:D: Int:D $value) {
  450. nqp::push_i(self, $value);
  451. self
  452. }
  453. multi method push(intarray:D: Mu \value) {
  454. X::TypeCheck.new(
  455. operation => 'push to int array',
  456. got => value,
  457. expected => T,
  458. ).throw;
  459. }
  460. multi method append(intarray:D: int $value) {
  461. nqp::push_i(self, $value);
  462. self
  463. }
  464. multi method append(intarray:D: Int:D $value) {
  465. nqp::push_i(self, $value);
  466. self
  467. }
  468. multi method append(intarray:D: int @values) {
  469. nqp::splice(self,@values,nqp::elems(self),0)
  470. }
  471. multi method append(intarray:D: @values) {
  472. fail X::Cannot::Lazy.new(:action<append>, :what(self.^name))
  473. if @values.is-lazy;
  474. nqp::push_i(self, $_) for flat @values;
  475. self
  476. }
  477. method pop(intarray:D: --> int) {
  478. nqp::elems(self) > 0
  479. ?? nqp::pop_i(self)
  480. !! die X::Cannot::Empty.new(:action<pop>, :what(self.^name));
  481. }
  482. method shift(intarray:D: --> int) {
  483. nqp::elems(self) > 0
  484. ?? nqp::shift_i(self)
  485. !! die X::Cannot::Empty.new(:action<shift>, :what(self.^name));
  486. }
  487. multi method unshift(intarray:D: int $value) {
  488. nqp::unshift_i(self, $value);
  489. self
  490. }
  491. multi method unshift(intarray:D: Int:D $value) {
  492. nqp::unshift_i(self, $value);
  493. self
  494. }
  495. multi method unshift(intarray:D: @values) {
  496. fail X::Cannot::Lazy.new(:action<unshift>, :what(self.^name))
  497. if @values.is-lazy;
  498. nqp::unshift_i(self, @values.pop) while @values;
  499. self
  500. }
  501. multi method unshift(intarray:D: Mu \value) {
  502. X::TypeCheck.new(
  503. operation => 'unshift to int array',
  504. got => value,
  505. expected => T,
  506. ).throw;
  507. }
  508. multi method splice(intarray:D: $offset=0, $size=Whatever, *@values) {
  509. fail X::Cannot::Lazy.new(:action('splice in'))
  510. if @values.is-lazy;
  511. my $elems = self.elems;
  512. my int $o = nqp::istype($offset,Callable)
  513. ?? $offset($elems)
  514. !! nqp::istype($offset,Whatever)
  515. ?? $elems
  516. !! $offset.Int;
  517. X::OutOfRange.new(
  518. :what('Offset argument to splice'),
  519. :got($o),
  520. :range("0..$elems"),
  521. ).fail if $o < 0 || $o > $elems; # one after list allowed for "push"
  522. my int $s = nqp::istype($size,Callable)
  523. ?? $size($elems - $o)
  524. !! !defined($size) || nqp::istype($size,Whatever)
  525. ?? $elems - ($o min $elems)
  526. !! $size.Int;
  527. X::OutOfRange.new(
  528. :what('Size argument to splice'),
  529. :got($s),
  530. :range("0..^{$elems - $o}"),
  531. ).fail if $s < 0;
  532. my @ret := nqp::create(self);
  533. my int $i = $o;
  534. my int $n = ($elems min $o + $s) - 1;
  535. while $i <= $n {
  536. nqp::push_i(@ret, nqp::atpos_i(self, $i));
  537. $i = $i + 1;
  538. }
  539. my @splicees := nqp::create(self);
  540. nqp::push_i(@splicees, @values.shift) while @values;
  541. nqp::splice(self, @splicees, $o, $s);
  542. @ret;
  543. }
  544. multi method min(intarray:D:) {
  545. nqp::if(
  546. (my int $elems = self.elems),
  547. nqp::stmts(
  548. (my int $i),
  549. (my int $min = nqp::atpos_i(self,0)),
  550. nqp::while(
  551. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  552. nqp::if(
  553. nqp::islt_i(nqp::atpos_i(self,$i),$min),
  554. ($min = nqp::atpos_i(self,$i))
  555. )
  556. ),
  557. $min
  558. ),
  559. Inf
  560. )
  561. }
  562. multi method max(intarray:D:) {
  563. nqp::if(
  564. (my int $elems = self.elems),
  565. nqp::stmts(
  566. (my int $i),
  567. (my int $max = nqp::atpos_i(self,0)),
  568. nqp::while(
  569. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  570. nqp::if(
  571. nqp::isgt_i(nqp::atpos_i(self,$i),$max),
  572. ($max = nqp::atpos_i(self,$i))
  573. )
  574. ),
  575. $max
  576. ),
  577. -Inf
  578. )
  579. }
  580. multi method minmax(intarray:D:) {
  581. nqp::if(
  582. (my int $elems = self.elems),
  583. nqp::stmts(
  584. (my int $i),
  585. (my int $min =
  586. my int $max = nqp::atpos_i(self,0)),
  587. nqp::while(
  588. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  589. nqp::if(
  590. nqp::islt_i(nqp::atpos_i(self,$i),$min),
  591. ($min = nqp::atpos_i(self,$i)),
  592. nqp::if(
  593. nqp::isgt_i(nqp::atpos_i(self,$i),$max),
  594. ($max = nqp::atpos_i(self,$i))
  595. )
  596. )
  597. ),
  598. Range.new($min,$max)
  599. ),
  600. Range.new(Inf,-Inf)
  601. )
  602. }
  603. method iterator(intarray:D:) {
  604. class :: does Iterator {
  605. has int $!i;
  606. has $!array; # Native array we're iterating
  607. method !SET-SELF(\array) {
  608. $!array := nqp::decont(array);
  609. $!i = -1;
  610. self
  611. }
  612. method new(\array) { nqp::create(self)!SET-SELF(array) }
  613. method pull-one() is raw {
  614. ($!i = $!i + 1) < nqp::elems($!array)
  615. ?? nqp::atposref_i($!array,$!i)
  616. !! IterationEnd
  617. }
  618. method push-all($target --> IterationEnd) {
  619. my int $i = $!i;
  620. my int $elems = nqp::elems($!array);
  621. $target.push(nqp::atposref_i($!array,$i))
  622. while ($i = $i + 1) < $elems;
  623. $!i = $i;
  624. }
  625. }.new(self)
  626. }
  627. method reverse(intarray:D:) is nodal {
  628. nqp::stmts(
  629. (my int $elems = nqp::elems(self)),
  630. (my int $last = nqp::sub_i($elems,1)),
  631. (my int $i = -1),
  632. (my $to := nqp::clone(self)),
  633. nqp::while(
  634. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  635. nqp::bindpos_i($to,nqp::sub_i($last,$i),
  636. nqp::atpos_i(self,$i))
  637. ),
  638. $to
  639. )
  640. }
  641. method rotate(intarray:D: Int(Cool) $rotate = 1) is nodal {
  642. nqp::stmts(
  643. (my int $elems = nqp::elems(self)),
  644. (my $to := nqp::clone(self)),
  645. (my int $i = -1),
  646. (my int $j =
  647. nqp::mod_i(nqp::sub_i(nqp::sub_i($elems,1),$rotate),$elems)),
  648. nqp::if(nqp::islt_i($j,0),($j = nqp::add_i($j,$elems))),
  649. nqp::while(
  650. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  651. nqp::bindpos_i(
  652. $to,
  653. ($j = nqp::mod_i(nqp::add_i($j,1),$elems)),
  654. nqp::atpos_i(self,$i)
  655. ),
  656. ),
  657. $to
  658. )
  659. }
  660. # https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation
  661. multi method sort(intarray:D:) {
  662. nqp::if(
  663. nqp::isgt_i((my int $n = nqp::elems(self)),2),
  664. # $A has the items to sort; $B is a work array
  665. nqp::stmts(
  666. (my Mu $A := nqp::clone(self)),
  667. (my Mu $B := nqp::setelems(nqp::create(self),$n)),
  668. # Each 1-element run in $A is already "sorted"
  669. # Make successively longer sorted runs of length 2, 4, 8, 16...
  670. # until $A is wholly sorted
  671. (my int $width = 1),
  672. nqp::while(
  673. nqp::islt_i($width,$n),
  674. nqp::stmts(
  675. (my int $l = 0),
  676. # $A is full of runs of length $width
  677. nqp::while(
  678. nqp::islt_i($l,$n),
  679. nqp::stmts(
  680. (my int $left = $l),
  681. (my int $right = nqp::add_i($l,$width)),
  682. nqp::if(nqp::isge_i($right,$n),($right = $n)),
  683. (my int $end =
  684. nqp::add_i($l,nqp::add_i($width,$width))),
  685. nqp::if(nqp::isge_i($end,$n),($end = $n)),
  686. (my int $i = $left),
  687. (my int $j = $right),
  688. (my int $k = nqp::sub_i($left,1)),
  689. # Merge two runs: $A[i .. i+width-1] and
  690. # $A[i+width .. i+2*width-1]
  691. # to $B or copy $A[i..n-1] to $B[] ( if(i+width >= n) )
  692. nqp::while(
  693. nqp::islt_i(($k = nqp::add_i($k,1)),$end),
  694. nqp::if(
  695. nqp::islt_i($i,$right) && (
  696. nqp::isge_i($j,$end)
  697. || nqp::islt_i(
  698. nqp::atpos_i($A,$i),
  699. nqp::atpos_i($A,$j)
  700. )
  701. ),
  702. nqp::stmts(
  703. (nqp::bindpos_i($B,$k,nqp::atpos_i($A,$i))),
  704. ($i = nqp::add_i($i,1))
  705. ),
  706. nqp::stmts(
  707. (nqp::bindpos_i($B,$k,nqp::atpos_i($A,$j))),
  708. ($j = nqp::add_i($j,1))
  709. )
  710. )
  711. ),
  712. ($l = nqp::add_i($l,nqp::add_i($width,$width)))
  713. )
  714. ),
  715. # Now work array $B is full of runs of length 2*width.
  716. # Copy array B to array A for next iteration. A more
  717. # efficient implementation would swap the roles of A and B.
  718. (my Mu $temp := $B),($B := $A),($A := $temp), # swap
  719. # Now array $A is full of runs of length 2*width.
  720. ($width = nqp::add_i($width,$width))
  721. )
  722. ),
  723. $A
  724. ),
  725. nqp::if(
  726. nqp::islt_i($n,2)
  727. || nqp::isle_i(nqp::atpos_i(self,0),nqp::atpos_i(self,1)),
  728. nqp::clone(self), # we already have the result
  729. nqp::stmts(
  730. (my $R := nqp::setelems(nqp::create(self),2)),
  731. nqp::bindpos_i($R,0,nqp::atpos_i(self,1)),
  732. nqp::bindpos_i($R,1,nqp::atpos_i(self,0)),
  733. $R
  734. )
  735. )
  736. )
  737. }
  738. #- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
  739. #- end of generated part of intarray role -------------------------------------
  740. method join(intarray:D: $delim = '') {
  741. my int $elems = nqp::elems(self);
  742. my $list := nqp::setelems(nqp::list_s,$elems);
  743. my int $i = -1;
  744. nqp::bindpos_s($list,$i,
  745. nqp::tostr_I(nqp::p6box_i(nqp::atpos_i(self,$i))))
  746. while nqp::islt_i(++$i,$elems);
  747. nqp::join($delim.Str,$list)
  748. }
  749. multi method STORE(intarray:D: Range:D $range) {
  750. nqp::if(
  751. $range.is-int,
  752. nqp::stmts(
  753. (my int $val = $range.min + $range.excludes-min),
  754. (my int $max = $range.max - $range.excludes-max),
  755. nqp::setelems(self, nqp::add_i(nqp::sub_i($max,$val),1)),
  756. (my int $i = -1),
  757. ($val = nqp::sub_i($val,1)),
  758. nqp::while(
  759. nqp::isle_i(($val = nqp::add_i($val,1)),$max),
  760. nqp::bindpos_i(self,($i = nqp::add_i($i,1)),$val)
  761. ),
  762. self
  763. ),
  764. (die "Can only initialize an int array with an int Range")
  765. )
  766. }
  767. }
  768. my role numarray[::T] does Positional[T] is array_type(T) {
  769. #- start of generated part of numarray role -----------------------------------
  770. #- Generated on 2017-03-15T11:21:04+01:00 by tools/build/makeNATIVE_ARRAY.pl6
  771. #- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
  772. multi method AT-POS(numarray:D: int $idx) is raw {
  773. nqp::atposref_n(self, $idx)
  774. }
  775. multi method AT-POS(numarray:D: Int:D $idx) is raw {
  776. nqp::atposref_n(self, $idx)
  777. }
  778. multi method ASSIGN-POS(numarray:D: int $idx, num $value) {
  779. nqp::bindpos_n(self, $idx, $value)
  780. }
  781. multi method ASSIGN-POS(numarray:D: Int:D $idx, num $value) {
  782. nqp::bindpos_n(self, $idx, $value)
  783. }
  784. multi method ASSIGN-POS(numarray:D: int $idx, Num:D $value) {
  785. nqp::bindpos_n(self, $idx, $value)
  786. }
  787. multi method ASSIGN-POS(numarray:D: Int:D $idx, Num:D $value) {
  788. nqp::bindpos_n(self, $idx, $value)
  789. }
  790. multi method ASSIGN-POS(numarray:D: Any $idx, Mu \value) {
  791. X::TypeCheck.new(
  792. operation => "assignment to num array element #$idx",
  793. got => value,
  794. expected => T,
  795. ).throw;
  796. }
  797. multi method STORE(numarray:D: $value) {
  798. nqp::bindpos_n(self, 0, nqp::unbox_n($value));
  799. self
  800. }
  801. multi method STORE(numarray:D: num @values) {
  802. nqp::splice(self,@values,0,0)
  803. }
  804. multi method STORE(numarray:D: @values) {
  805. my int $elems = @values.elems;
  806. nqp::setelems(self, $elems);
  807. my int $i = -1;
  808. nqp::bindpos_n(self, $i,
  809. nqp::unbox_n(@values.AT-POS($i)))
  810. while nqp::islt_i($i = nqp::add_i($i,1),$elems);
  811. self
  812. }
  813. multi method push(numarray:D: num $value) {
  814. nqp::push_n(self, $value);
  815. self
  816. }
  817. multi method push(numarray:D: Num:D $value) {
  818. nqp::push_n(self, $value);
  819. self
  820. }
  821. multi method push(numarray:D: Mu \value) {
  822. X::TypeCheck.new(
  823. operation => 'push to num array',
  824. got => value,
  825. expected => T,
  826. ).throw;
  827. }
  828. multi method append(numarray:D: num $value) {
  829. nqp::push_n(self, $value);
  830. self
  831. }
  832. multi method append(numarray:D: Num:D $value) {
  833. nqp::push_n(self, $value);
  834. self
  835. }
  836. multi method append(numarray:D: num @values) {
  837. nqp::splice(self,@values,nqp::elems(self),0)
  838. }
  839. multi method append(numarray:D: @values) {
  840. fail X::Cannot::Lazy.new(:action<append>, :what(self.^name))
  841. if @values.is-lazy;
  842. nqp::push_n(self, $_) for flat @values;
  843. self
  844. }
  845. method pop(numarray:D: --> num) {
  846. nqp::elems(self) > 0
  847. ?? nqp::pop_n(self)
  848. !! die X::Cannot::Empty.new(:action<pop>, :what(self.^name));
  849. }
  850. method shift(numarray:D: --> num) {
  851. nqp::elems(self) > 0
  852. ?? nqp::shift_n(self)
  853. !! die X::Cannot::Empty.new(:action<shift>, :what(self.^name));
  854. }
  855. multi method unshift(numarray:D: num $value) {
  856. nqp::unshift_n(self, $value);
  857. self
  858. }
  859. multi method unshift(numarray:D: Num:D $value) {
  860. nqp::unshift_n(self, $value);
  861. self
  862. }
  863. multi method unshift(numarray:D: @values) {
  864. fail X::Cannot::Lazy.new(:action<unshift>, :what(self.^name))
  865. if @values.is-lazy;
  866. nqp::unshift_n(self, @values.pop) while @values;
  867. self
  868. }
  869. multi method unshift(numarray:D: Mu \value) {
  870. X::TypeCheck.new(
  871. operation => 'unshift to num array',
  872. got => value,
  873. expected => T,
  874. ).throw;
  875. }
  876. multi method splice(numarray:D: $offset=0, $size=Whatever, *@values) {
  877. fail X::Cannot::Lazy.new(:action('splice in'))
  878. if @values.is-lazy;
  879. my $elems = self.elems;
  880. my int $o = nqp::istype($offset,Callable)
  881. ?? $offset($elems)
  882. !! nqp::istype($offset,Whatever)
  883. ?? $elems
  884. !! $offset.Int;
  885. X::OutOfRange.new(
  886. :what('Offset argument to splice'),
  887. :got($o),
  888. :range("0..$elems"),
  889. ).fail if $o < 0 || $o > $elems; # one after list allowed for "push"
  890. my int $s = nqp::istype($size,Callable)
  891. ?? $size($elems - $o)
  892. !! !defined($size) || nqp::istype($size,Whatever)
  893. ?? $elems - ($o min $elems)
  894. !! $size.Int;
  895. X::OutOfRange.new(
  896. :what('Size argument to splice'),
  897. :got($s),
  898. :range("0..^{$elems - $o}"),
  899. ).fail if $s < 0;
  900. my @ret := nqp::create(self);
  901. my int $i = $o;
  902. my int $n = ($elems min $o + $s) - 1;
  903. while $i <= $n {
  904. nqp::push_n(@ret, nqp::atpos_n(self, $i));
  905. $i = $i + 1;
  906. }
  907. my @splicees := nqp::create(self);
  908. nqp::push_n(@splicees, @values.shift) while @values;
  909. nqp::splice(self, @splicees, $o, $s);
  910. @ret;
  911. }
  912. multi method min(numarray:D:) {
  913. nqp::if(
  914. (my int $elems = self.elems),
  915. nqp::stmts(
  916. (my int $i),
  917. (my num $min = nqp::atpos_n(self,0)),
  918. nqp::while(
  919. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  920. nqp::if(
  921. nqp::islt_n(nqp::atpos_n(self,$i),$min),
  922. ($min = nqp::atpos_n(self,$i))
  923. )
  924. ),
  925. $min
  926. ),
  927. Inf
  928. )
  929. }
  930. multi method max(numarray:D:) {
  931. nqp::if(
  932. (my int $elems = self.elems),
  933. nqp::stmts(
  934. (my int $i),
  935. (my num $max = nqp::atpos_n(self,0)),
  936. nqp::while(
  937. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  938. nqp::if(
  939. nqp::isgt_n(nqp::atpos_n(self,$i),$max),
  940. ($max = nqp::atpos_n(self,$i))
  941. )
  942. ),
  943. $max
  944. ),
  945. -Inf
  946. )
  947. }
  948. multi method minmax(numarray:D:) {
  949. nqp::if(
  950. (my int $elems = self.elems),
  951. nqp::stmts(
  952. (my int $i),
  953. (my num $min =
  954. my num $max = nqp::atpos_n(self,0)),
  955. nqp::while(
  956. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  957. nqp::if(
  958. nqp::islt_n(nqp::atpos_n(self,$i),$min),
  959. ($min = nqp::atpos_n(self,$i)),
  960. nqp::if(
  961. nqp::isgt_n(nqp::atpos_n(self,$i),$max),
  962. ($max = nqp::atpos_n(self,$i))
  963. )
  964. )
  965. ),
  966. Range.new($min,$max)
  967. ),
  968. Range.new(Inf,-Inf)
  969. )
  970. }
  971. method iterator(numarray:D:) {
  972. class :: does Iterator {
  973. has int $!i;
  974. has $!array; # Native array we're iterating
  975. method !SET-SELF(\array) {
  976. $!array := nqp::decont(array);
  977. $!i = -1;
  978. self
  979. }
  980. method new(\array) { nqp::create(self)!SET-SELF(array) }
  981. method pull-one() is raw {
  982. ($!i = $!i + 1) < nqp::elems($!array)
  983. ?? nqp::atposref_n($!array,$!i)
  984. !! IterationEnd
  985. }
  986. method push-all($target --> IterationEnd) {
  987. my int $i = $!i;
  988. my int $elems = nqp::elems($!array);
  989. $target.push(nqp::atposref_n($!array,$i))
  990. while ($i = $i + 1) < $elems;
  991. $!i = $i;
  992. }
  993. }.new(self)
  994. }
  995. method reverse(numarray:D:) is nodal {
  996. nqp::stmts(
  997. (my int $elems = nqp::elems(self)),
  998. (my int $last = nqp::sub_i($elems,1)),
  999. (my int $i = -1),
  1000. (my $to := nqp::clone(self)),
  1001. nqp::while(
  1002. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1003. nqp::bindpos_n($to,nqp::sub_i($last,$i),
  1004. nqp::atpos_n(self,$i))
  1005. ),
  1006. $to
  1007. )
  1008. }
  1009. method rotate(numarray:D: Int(Cool) $rotate = 1) is nodal {
  1010. nqp::stmts(
  1011. (my int $elems = nqp::elems(self)),
  1012. (my $to := nqp::clone(self)),
  1013. (my int $i = -1),
  1014. (my int $j =
  1015. nqp::mod_i(nqp::sub_i(nqp::sub_i($elems,1),$rotate),$elems)),
  1016. nqp::if(nqp::islt_i($j,0),($j = nqp::add_i($j,$elems))),
  1017. nqp::while(
  1018. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1019. nqp::bindpos_n(
  1020. $to,
  1021. ($j = nqp::mod_i(nqp::add_i($j,1),$elems)),
  1022. nqp::atpos_n(self,$i)
  1023. ),
  1024. ),
  1025. $to
  1026. )
  1027. }
  1028. # https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation
  1029. multi method sort(numarray:D:) {
  1030. nqp::if(
  1031. nqp::isgt_i((my int $n = nqp::elems(self)),2),
  1032. # $A has the items to sort; $B is a work array
  1033. nqp::stmts(
  1034. (my Mu $A := nqp::clone(self)),
  1035. (my Mu $B := nqp::setelems(nqp::create(self),$n)),
  1036. # Each 1-element run in $A is already "sorted"
  1037. # Make successively longer sorted runs of length 2, 4, 8, 16...
  1038. # until $A is wholly sorted
  1039. (my int $width = 1),
  1040. nqp::while(
  1041. nqp::islt_i($width,$n),
  1042. nqp::stmts(
  1043. (my int $l = 0),
  1044. # $A is full of runs of length $width
  1045. nqp::while(
  1046. nqp::islt_i($l,$n),
  1047. nqp::stmts(
  1048. (my int $left = $l),
  1049. (my int $right = nqp::add_i($l,$width)),
  1050. nqp::if(nqp::isge_i($right,$n),($right = $n)),
  1051. (my int $end =
  1052. nqp::add_i($l,nqp::add_i($width,$width))),
  1053. nqp::if(nqp::isge_i($end,$n),($end = $n)),
  1054. (my int $i = $left),
  1055. (my int $j = $right),
  1056. (my int $k = nqp::sub_i($left,1)),
  1057. # Merge two runs: $A[i .. i+width-1] and
  1058. # $A[i+width .. i+2*width-1]
  1059. # to $B or copy $A[i..n-1] to $B[] ( if(i+width >= n) )
  1060. nqp::while(
  1061. nqp::islt_i(($k = nqp::add_i($k,1)),$end),
  1062. nqp::if(
  1063. nqp::islt_i($i,$right) && (
  1064. nqp::isge_i($j,$end)
  1065. || nqp::islt_n(
  1066. nqp::atpos_n($A,$i),
  1067. nqp::atpos_n($A,$j)
  1068. )
  1069. ),
  1070. nqp::stmts(
  1071. (nqp::bindpos_n($B,$k,nqp::atpos_n($A,$i))),
  1072. ($i = nqp::add_i($i,1))
  1073. ),
  1074. nqp::stmts(
  1075. (nqp::bindpos_n($B,$k,nqp::atpos_n($A,$j))),
  1076. ($j = nqp::add_i($j,1))
  1077. )
  1078. )
  1079. ),
  1080. ($l = nqp::add_i($l,nqp::add_i($width,$width)))
  1081. )
  1082. ),
  1083. # Now work array $B is full of runs of length 2*width.
  1084. # Copy array B to array A for next iteration. A more
  1085. # efficient implementation would swap the roles of A and B.
  1086. (my Mu $temp := $B),($B := $A),($A := $temp), # swap
  1087. # Now array $A is full of runs of length 2*width.
  1088. ($width = nqp::add_i($width,$width))
  1089. )
  1090. ),
  1091. $A
  1092. ),
  1093. nqp::if(
  1094. nqp::islt_i($n,2)
  1095. || nqp::isle_n(nqp::atpos_n(self,0),nqp::atpos_n(self,1)),
  1096. nqp::clone(self), # we already have the result
  1097. nqp::stmts(
  1098. (my $R := nqp::setelems(nqp::create(self),2)),
  1099. nqp::bindpos_n($R,0,nqp::atpos_n(self,1)),
  1100. nqp::bindpos_n($R,1,nqp::atpos_n(self,0)),
  1101. $R
  1102. )
  1103. )
  1104. )
  1105. }
  1106. #- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
  1107. #- end of generated part of numarray role -------------------------------------
  1108. multi method STORE(numarray:D: Range:D $range) {
  1109. my num $val = $range.min;
  1110. $val = $val + 1 if $range.excludes-min;
  1111. my num $max = $range.max;
  1112. $max = $max - 1 if $range.excludes-max;
  1113. fail X::Cannot::Lazy.new(:action<initialize>,:what(self.^name))
  1114. if $val == -Inf || $max == Inf;
  1115. nqp::setelems(self, ($max - $val + 1).Int );
  1116. my int $i;
  1117. while $val <= $max {
  1118. nqp::bindpos_n(self, $i, $val);
  1119. $val = $val + 1;
  1120. $i = $i + 1;
  1121. }
  1122. self
  1123. }
  1124. }
  1125. role shapedarray does Rakudo::Internals::ShapedArrayCommon {
  1126. method shape() {
  1127. nqp::stmts(
  1128. (my $idims := nqp::dimensions(self)),
  1129. (my int $dims = nqp::elems($idims)),
  1130. (my $odims := nqp::setelems(nqp::create(IterationBuffer),$dims)),
  1131. (my int $i = -1),
  1132. nqp::while(
  1133. nqp::islt_i(($i = nqp::add_i($i,1)),$dims),
  1134. nqp::bindpos($odims,$i,nqp::atpos_i($idims,$i))
  1135. ),
  1136. nqp::p6bindattrinvres(nqp::create(List),List,'$!reified',$odims)
  1137. )
  1138. }
  1139. multi method EXISTS-POS(::?CLASS:D: **@indices) {
  1140. nqp::p6bool(
  1141. nqp::stmts(
  1142. (my int $numdims = nqp::numdimensions(self)),
  1143. (my int $numind = @indices.elems), # reifies
  1144. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  1145. nqp::if(
  1146. nqp::isle_i($numind,$numdims),
  1147. nqp::stmts(
  1148. (my $dims := nqp::dimensions(self)),
  1149. (my int $i = -1),
  1150. nqp::while(
  1151. nqp::islt_i(($i = nqp::add_i($i,1)),$numind)
  1152. && nqp::isge_i(nqp::atpos($indices,$i),0)
  1153. && nqp::islt_i(
  1154. nqp::atpos($indices,$i),
  1155. nqp::atpos_i($dims,$i)
  1156. ),
  1157. nqp::null
  1158. ),
  1159. nqp::iseq_i($i,$numind)
  1160. )
  1161. )
  1162. )
  1163. )
  1164. }
  1165. proto method STORE(|) { * }
  1166. multi method STORE(::?CLASS:D: Mu \item) {
  1167. X::Assignment::ToShaped.new(shape => self.shape).throw
  1168. }
  1169. }
  1170. #- start of generated part of shapedintarray role -----------------------------
  1171. #- Generated on 2017-01-22T22:56:03+01:00 by tools/build/makeNATIVE_SHAPED_ARRAY.pl6
  1172. #- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
  1173. role shapedintarray does shapedarray {
  1174. multi method AT-POS(::?CLASS:D: **@indices) is raw {
  1175. nqp::if(
  1176. nqp::iseq_i(
  1177. (my int $numdims = nqp::numdimensions(self)),
  1178. (my int $numind = @indices.elems), # reifies
  1179. ),
  1180. nqp::stmts(
  1181. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  1182. (my $idxs := nqp::list_i),
  1183. nqp::while( # native index list
  1184. nqp::isge_i(($numdims = nqp::sub_i($numdims,1)),0),
  1185. nqp::push_i($idxs,nqp::shift($indices))
  1186. ),
  1187. nqp::multidimref_i(self,$idxs)
  1188. ),
  1189. nqp::if(
  1190. nqp::isgt_i($numind,$numdims),
  1191. X::TooManyDimensions.new(
  1192. operation => 'access',
  1193. got-dimensions => $numind,
  1194. needed-dimensions => $numdims
  1195. ).throw,
  1196. X::NYI.new(
  1197. feature => "Partially dimensioned views of shaped arrays"
  1198. ).throw
  1199. )
  1200. )
  1201. }
  1202. multi method ASSIGN-POS(::?CLASS:D: **@indices) {
  1203. nqp::stmts(
  1204. (my int $value = @indices.pop),
  1205. nqp::if(
  1206. nqp::iseq_i(
  1207. (my int $numdims = nqp::numdimensions(self)),
  1208. (my int $numind = @indices.elems), # reifies
  1209. ),
  1210. nqp::stmts(
  1211. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  1212. (my $idxs := nqp::list_i),
  1213. nqp::while( # native index list
  1214. nqp::isge_i(($numdims = nqp::sub_i($numdims,1)),0),
  1215. nqp::push_i($idxs,nqp::shift($indices))
  1216. ),
  1217. nqp::bindposnd_i(self, $idxs, $value)
  1218. ),
  1219. nqp::if(
  1220. nqp::isgt_i($numind,$numdims),
  1221. X::TooManyDimensions,
  1222. X::NotEnoughDimensions
  1223. ).new(
  1224. operation => 'assign to',
  1225. got-dimensions => $numind,
  1226. needed-dimensions => $numdims
  1227. ).throw
  1228. )
  1229. )
  1230. }
  1231. sub NATCPY(Mu \to, Mu \from) is raw {
  1232. class :: does Rakudo::Iterator::ShapeLeaf {
  1233. has Mu $!from;
  1234. method INIT(Mu \to, Mu \from) {
  1235. nqp::stmts(
  1236. ($!from := from),
  1237. self.SET-SELF(to)
  1238. )
  1239. }
  1240. method new(Mu \to, Mu \from) {
  1241. nqp::create(self).INIT(to,from)
  1242. }
  1243. method result(--> Nil) {
  1244. nqp::bindposnd_i($!list,$!indices,
  1245. nqp::multidimref_i($!from,$!indices))
  1246. }
  1247. }.new(to,from).sink-all;
  1248. to
  1249. }
  1250. sub OBJCPY(Mu \to, Mu \from) is raw {
  1251. class :: does Rakudo::Iterator::ShapeLeaf {
  1252. has Mu $!from;
  1253. method INIT(Mu \to, Mu \from) {
  1254. nqp::stmts(
  1255. ($!from := nqp::getattr(from,List,'$!reified')),
  1256. self.SET-SELF(to)
  1257. )
  1258. }
  1259. method new(Mu \to, Mu \from) {
  1260. nqp::create(self).INIT(to,from)
  1261. }
  1262. method result(--> Nil) {
  1263. nqp::bindposnd_i($!list,$!indices,
  1264. nqp::atposnd($!from,$!indices))
  1265. }
  1266. }.new(to,from).sink-all;
  1267. to
  1268. }
  1269. sub ITERCPY(Mu \to, Mu \from) is raw {
  1270. class :: does Rakudo::Iterator::ShapeBranch {
  1271. has $!iterators;
  1272. method INIT(\to,\from) {
  1273. nqp::stmts(
  1274. self.SET-SELF(to),
  1275. ($!iterators := nqp::setelems(
  1276. nqp::list(from.iterator),
  1277. nqp::add_i($!maxdim,1)
  1278. )),
  1279. self
  1280. )
  1281. }
  1282. method new(\to,\from) { nqp::create(self).INIT(to,from) }
  1283. method done(--> Nil) {
  1284. nqp::unless( # verify lowest
  1285. nqp::atpos($!iterators,0).is-lazy # finite iterator
  1286. || nqp::eqaddr( # and something there
  1287. nqp::atpos($!iterators,0).pull-one,IterationEnd),
  1288. nqp::atposnd_i($!list,$!indices) # boom!
  1289. )
  1290. }
  1291. method process(--> Nil) {
  1292. nqp::stmts(
  1293. (my int $i = $!level),
  1294. nqp::while(
  1295. nqp::isle_i(($i = nqp::add_i($i,1)),$!maxdim),
  1296. nqp::if(
  1297. nqp::eqaddr((my $item := # exhausted ?
  1298. nqp::atpos($!iterators,nqp::sub_i($i,1)).pull-one),
  1299. IterationEnd
  1300. ),
  1301. nqp::bindpos($!iterators,$i, # add an empty one
  1302. Rakudo::Iterator.Empty),
  1303. nqp::if( # is it an iterator?
  1304. nqp::istype($item,Iterable) && nqp::isconcrete($item),
  1305. nqp::bindpos($!iterators,$i,$item.iterator),
  1306. X::Assignment::ToShaped.new(shape => $!dims).throw
  1307. )
  1308. )
  1309. ),
  1310. (my $iter := nqp::atpos($!iterators,$!maxdim)),
  1311. nqp::until( # loop over highest dim
  1312. nqp::eqaddr((my $pulled := $iter.pull-one),IterationEnd)
  1313. || nqp::isgt_i(nqp::atpos_i($!indices,$!maxdim),$!maxind),
  1314. nqp::stmts(
  1315. nqp::bindposnd_i($!list,$!indices,$pulled),
  1316. nqp::bindpos_i($!indices,$!maxdim, # increment index
  1317. nqp::add_i(nqp::atpos_i($!indices,$!maxdim),1))
  1318. )
  1319. ),
  1320. nqp::unless(
  1321. nqp::eqaddr($pulled,IterationEnd) # if not exhausted
  1322. || nqp::isle_i( # and index too high
  1323. nqp::atpos_i($!indices,$!maxdim),$!maxind)
  1324. || $iter.is-lazy, # and not lazy
  1325. nqp::atposnd_i($!list,$!indices) # boom!
  1326. )
  1327. )
  1328. }
  1329. }.new(to,from).sink-all;
  1330. to
  1331. }
  1332. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  1333. nqp::if(
  1334. EQV_DIMENSIONS(self,from),
  1335. NATCPY(self,from),
  1336. X::Assignment::ArrayShapeMismatch.new(
  1337. source-shape => from.shape,
  1338. target-shape => self.shape
  1339. ).throw
  1340. )
  1341. }
  1342. multi method STORE(::?CLASS:D: array:D \from) {
  1343. nqp::if(
  1344. nqp::istype(from.of,Int),
  1345. nqp::if(
  1346. EQV_DIMENSIONS(self,from),
  1347. NATCPY(self,from),
  1348. X::Assignment::ArrayShapeMismatch.new(
  1349. source-shape => from.shape,
  1350. target-shape => self.shape
  1351. ).throw
  1352. ),
  1353. X::TypeCheck::Assignment.new(
  1354. symbol => self.^name ~ '[' ~ self.shape.join(';') ~ ']',
  1355. expected => Int,
  1356. got => from.of
  1357. ).throw
  1358. )
  1359. }
  1360. multi method STORE(::?CLASS:D: Iterable:D \from) {
  1361. nqp::if(
  1362. nqp::can(from,'shape'),
  1363. nqp::if(
  1364. from.shape eqv self.shape,
  1365. OBJCPY(self,from),
  1366. X::Assignment::ArrayShapeMismatch.new(
  1367. source-shape => from.shape,
  1368. target-shape => self.shape
  1369. ).throw
  1370. ),
  1371. ITERCPY(self,from)
  1372. )
  1373. }
  1374. method iterator(::?CLASS:D:) {
  1375. class :: does Rakudo::Iterator::ShapeLeaf {
  1376. method result() is raw {
  1377. nqp::multidimref_i($!list,nqp::clone($!indices))
  1378. }
  1379. }.new(self)
  1380. }
  1381. multi method kv(::?CLASS:D:) {
  1382. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  1383. has int $!on-key;
  1384. method result() is raw {
  1385. nqp::if(
  1386. ($!on-key = nqp::not_i($!on-key)),
  1387. nqp::stmts(
  1388. (my $result := self.indices),
  1389. (nqp::bindpos_i($!indices,$!maxdim, # back 1 for next
  1390. nqp::sub_i(nqp::atpos_i($!indices,$!maxdim),1))),
  1391. $result
  1392. ),
  1393. nqp::multidimref_i($!list,nqp::clone($!indices))
  1394. )
  1395. }
  1396. # needs its own push-all since it fiddles with $!indices
  1397. method push-all($target --> IterationEnd) {
  1398. nqp::until(
  1399. nqp::eqaddr((my $pulled := self.pull-one),IterationEnd),
  1400. $target.push($pulled)
  1401. )
  1402. }
  1403. }.new(self))
  1404. }
  1405. multi method pairs(::?CLASS:D:) {
  1406. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  1407. method result() {
  1408. Pair.new(
  1409. self.indices,
  1410. nqp::multidimref_i($!list,nqp::clone($!indices))
  1411. )
  1412. }
  1413. }.new(self))
  1414. }
  1415. multi method antipairs(::?CLASS:D:) {
  1416. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  1417. method result() {
  1418. Pair.new(nqp::atposnd_i($!list,$!indices),self.indices)
  1419. }
  1420. }.new(self))
  1421. }
  1422. } # end of shapedintarray role
  1423. role shaped1intarray does shapedintarray {
  1424. multi method AT-POS(::?CLASS:D: int \one) is raw {
  1425. nqp::atposref_i(self,one)
  1426. }
  1427. multi method AT-POS(::?CLASS:D: Int:D \one) is raw {
  1428. nqp::atposref_i(self,one)
  1429. }
  1430. multi method ASSIGN-POS(::?CLASS:D: int \one, int \value) {
  1431. nqp::bindpos_i(self,one,value)
  1432. }
  1433. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, int \value) {
  1434. nqp::bindpos_i(self,one,value)
  1435. }
  1436. multi method ASSIGN-POS(::?CLASS:D: int \one, Int:D \value) {
  1437. nqp::bindpos_i(self,one,value)
  1438. }
  1439. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \value) {
  1440. nqp::bindpos_i(self,one,value)
  1441. }
  1442. multi method EXISTS-POS(::?CLASS:D: int \one) {
  1443. nqp::p6bool(
  1444. nqp::isge_i(one,0) && nqp::islt_i(one,nqp::elems(self))
  1445. )
  1446. }
  1447. multi method EXISTS-POS(::?CLASS:D: Int:D \one) {
  1448. nqp::p6bool(
  1449. nqp::isge_i(one,0) && nqp::islt_i(one,nqp::elems(self))
  1450. )
  1451. }
  1452. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  1453. nqp::if(
  1454. nqp::iseq_i((my int $elems = nqp::elems(self)),nqp::elems(from)),
  1455. nqp::stmts(
  1456. (my int $i = -1),
  1457. nqp::while(
  1458. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1459. nqp::bindpos_i(self,$i,nqp::atpos_i(from,$i))
  1460. ),
  1461. self
  1462. ),
  1463. X::Assignment::ArrayShapeMismatch.new(
  1464. source-shape => from.shape,
  1465. target-shape => self.shape
  1466. ).throw
  1467. )
  1468. }
  1469. multi method STORE(::?CLASS:D: Iterable:D \in) {
  1470. nqp::stmts(
  1471. (my \iter := in.iterator),
  1472. (my int $elems = nqp::elems(self)),
  1473. (my int $i = -1),
  1474. nqp::until(
  1475. nqp::eqaddr((my $pulled := iter.pull-one),IterationEnd)
  1476. || nqp::iseq_i(($i = nqp::add_i($i,1)),$elems),
  1477. nqp::bindpos_i(self,$i,$pulled)
  1478. ),
  1479. nqp::unless(
  1480. nqp::islt_i($i,$elems) || iter.is-lazy,
  1481. nqp::atpos_i(list,$i) # too many values on non-lazy it
  1482. ),
  1483. self
  1484. )
  1485. }
  1486. multi method STORE(::?CLASS:D: Int:D \item) {
  1487. nqp::stmts(
  1488. nqp::bindpos_i(self,0,item),
  1489. self
  1490. )
  1491. }
  1492. method iterator(::?CLASS:D:) {
  1493. class :: does Iterator {
  1494. has Mu $!list;
  1495. has int $!pos;
  1496. method !SET-SELF(Mu \list) {
  1497. nqp::stmts(
  1498. ($!list := list),
  1499. ($!pos = -1),
  1500. self
  1501. )
  1502. }
  1503. method new(Mu \list) { nqp::create(self)!SET-SELF(list) }
  1504. method pull-one() is raw {
  1505. nqp::if(
  1506. nqp::islt_i(
  1507. ($!pos = nqp::add_i($!pos,1)),
  1508. nqp::elems($!list)
  1509. ),
  1510. nqp::atposref_i($!list,$!pos),
  1511. IterationEnd
  1512. )
  1513. }
  1514. method push-all($target --> IterationEnd) {
  1515. nqp::stmts(
  1516. (my int $elems = nqp::elems($!list)),
  1517. (my int $i = -1),
  1518. nqp::while(
  1519. nqp::islt_i(($!pos = nqp::add_i($!pos,1)),$elems),
  1520. $target.push(nqp::atpos_i($!list,$!pos))
  1521. )
  1522. )
  1523. }
  1524. method count-only() { nqp::p6box_i(nqp::elems($!list)) }
  1525. method bool-only() { nqp::p6bool(nqp::elems($!list)) }
  1526. method sink-all(--> IterationEnd) {
  1527. $!pos = nqp::elems($!list)
  1528. }
  1529. }.new(self)
  1530. }
  1531. multi method kv(::?CLASS:D:) {
  1532. my int $i = -1;
  1533. my int $elems = nqp::add_i(nqp::elems(self),nqp::elems(self));
  1534. Seq.new(Rakudo::Iterator.Callable({
  1535. nqp::if(
  1536. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1537. nqp::if(
  1538. nqp::bitand_i($i,1),
  1539. nqp::atposref_i(self,nqp::bitshiftr_i($i,1)),
  1540. nqp::bitshiftr_i($i,1)
  1541. ),
  1542. IterationEnd
  1543. )
  1544. }))
  1545. }
  1546. multi method pairs(::?CLASS:D:) {
  1547. my int $i = -1;
  1548. my int $elems = nqp::elems(self);
  1549. Seq.new(Rakudo::Iterator.Callable({
  1550. nqp::if(
  1551. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1552. Pair.new($i,nqp::atposref_i(self,$i)),
  1553. IterationEnd
  1554. )
  1555. }))
  1556. }
  1557. multi method antipairs(::?CLASS:D:) {
  1558. Seq.new(Rakudo::Iterator.AntiPair(self.iterator))
  1559. }
  1560. method reverse(::?CLASS:D:) is nodal {
  1561. nqp::stmts(
  1562. (my int $elems = nqp::elems(self)),
  1563. (my int $last = nqp::sub_i($elems,1)),
  1564. (my int $i = -1),
  1565. (my $to := nqp::clone(self)),
  1566. nqp::while(
  1567. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1568. nqp::bindpos_i($to,nqp::sub_i($last,$i),
  1569. nqp::atpos_i(self,$i))
  1570. ),
  1571. $to
  1572. )
  1573. }
  1574. method rotate(::?CLASS:D: Int(Cool) $rotate = 1) is nodal {
  1575. nqp::stmts(
  1576. (my int $elems = nqp::elems(self)),
  1577. (my $to := nqp::clone(self)),
  1578. (my int $i = -1),
  1579. (my int $j =
  1580. nqp::mod_i(nqp::sub_i(nqp::sub_i($elems,1),$rotate),$elems)),
  1581. nqp::if(nqp::islt_i($j,0),($j = nqp::add_i($j,$elems))),
  1582. nqp::while(
  1583. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1584. nqp::bindpos_i(
  1585. $to,
  1586. ($j = nqp::mod_i(nqp::add_i($j,1),$elems)),
  1587. nqp::atpos_i(self,$i)
  1588. ),
  1589. ),
  1590. $to
  1591. )
  1592. }
  1593. } # end of shaped1intarray role
  1594. role shaped2intarray does shapedintarray {
  1595. multi method AT-POS(::?CLASS:D: int \one, int \two) is raw {
  1596. nqp::atpos2d_i(self,one,two)
  1597. }
  1598. multi method AT-POS(::?CLASS:D: Int:D \one, Int:D \two) is raw {
  1599. nqp::atpos2d_i(self,one,two)
  1600. }
  1601. multi method ASSIGN-POS(::?CLASS:D: int \one, int \two, Int:D \value) {
  1602. nqp::bindpos2d_i(self,one,two,value)
  1603. }
  1604. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \value) {
  1605. nqp::bindpos2d_i(self,one,two,value)
  1606. }
  1607. multi method EXISTS-POS(::?CLASS:D: int \one, int \two) {
  1608. nqp::p6bool(
  1609. nqp::isge_i(one,0)
  1610. && nqp::isge_i(two,0)
  1611. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  1612. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  1613. )
  1614. }
  1615. multi method EXISTS-POS(::?CLASS:D: Int:D \one, Int:D \two) {
  1616. nqp::p6bool(
  1617. nqp::isge_i(one,0)
  1618. && nqp::isge_i(two,0)
  1619. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  1620. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  1621. )
  1622. }
  1623. } # end of shaped2intarray role
  1624. role shaped3intarray does shapedintarray {
  1625. multi method AT-POS(::?CLASS:D: int \one, int \two, int \three) is raw {
  1626. nqp::atpos3d_i(self,one,two,three)
  1627. }
  1628. multi method AT-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three) is raw {
  1629. nqp::atpos3d_i(self,one,two,three)
  1630. }
  1631. multi method ASSIGN-POS(::?CLASS:D: int \one, int \two, int \three, Int:D \value) {
  1632. nqp::bindpos3d_i(self,one,two,three,value)
  1633. }
  1634. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three, Int:D \value) {
  1635. nqp::bindpos3d_i(self,one,two,three,value)
  1636. }
  1637. multi method EXISTS-POS(::?CLASS:D: int \one, int \two, int \three) {
  1638. nqp::p6bool(
  1639. nqp::isge_i(one,0)
  1640. && nqp::isge_i(two,0)
  1641. && nqp::isge_i(three,0)
  1642. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  1643. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  1644. && nqp::islt_i(three,nqp::atpos_i(nqp::dimensions(self),2))
  1645. )
  1646. }
  1647. multi method EXISTS-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three) {
  1648. nqp::p6bool(
  1649. nqp::isge_i(one,0)
  1650. && nqp::isge_i(two,0)
  1651. && nqp::isge_i(three,0)
  1652. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  1653. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  1654. && nqp::islt_i(three,nqp::atpos_i(nqp::dimensions(self),2))
  1655. )
  1656. }
  1657. } # end of shaped3intarray role
  1658. #- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
  1659. #- end of generated part of shapedintarray role -------------------------------
  1660. #- start of generated part of shapednumarray role -----------------------------
  1661. #- Generated on 2017-01-22T22:56:03+01:00 by tools/build/makeNATIVE_SHAPED_ARRAY.pl6
  1662. #- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
  1663. role shapednumarray does shapedarray {
  1664. multi method AT-POS(::?CLASS:D: **@indices) is raw {
  1665. nqp::if(
  1666. nqp::iseq_i(
  1667. (my int $numdims = nqp::numdimensions(self)),
  1668. (my int $numind = @indices.elems), # reifies
  1669. ),
  1670. nqp::stmts(
  1671. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  1672. (my $idxs := nqp::list_i),
  1673. nqp::while( # native index list
  1674. nqp::isge_i(($numdims = nqp::sub_i($numdims,1)),0),
  1675. nqp::push_i($idxs,nqp::shift($indices))
  1676. ),
  1677. nqp::multidimref_n(self,$idxs)
  1678. ),
  1679. nqp::if(
  1680. nqp::isgt_i($numind,$numdims),
  1681. X::TooManyDimensions.new(
  1682. operation => 'access',
  1683. got-dimensions => $numind,
  1684. needed-dimensions => $numdims
  1685. ).throw,
  1686. X::NYI.new(
  1687. feature => "Partially dimensioned views of shaped arrays"
  1688. ).throw
  1689. )
  1690. )
  1691. }
  1692. multi method ASSIGN-POS(::?CLASS:D: **@indices) {
  1693. nqp::stmts(
  1694. (my num $value = @indices.pop),
  1695. nqp::if(
  1696. nqp::iseq_i(
  1697. (my int $numdims = nqp::numdimensions(self)),
  1698. (my int $numind = @indices.elems), # reifies
  1699. ),
  1700. nqp::stmts(
  1701. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  1702. (my $idxs := nqp::list_i),
  1703. nqp::while( # native index list
  1704. nqp::isge_i(($numdims = nqp::sub_i($numdims,1)),0),
  1705. nqp::push_i($idxs,nqp::shift($indices))
  1706. ),
  1707. nqp::bindposnd_n(self, $idxs, $value)
  1708. ),
  1709. nqp::if(
  1710. nqp::isgt_i($numind,$numdims),
  1711. X::TooManyDimensions,
  1712. X::NotEnoughDimensions
  1713. ).new(
  1714. operation => 'assign to',
  1715. got-dimensions => $numind,
  1716. needed-dimensions => $numdims
  1717. ).throw
  1718. )
  1719. )
  1720. }
  1721. sub NATCPY(Mu \to, Mu \from) is raw {
  1722. class :: does Rakudo::Iterator::ShapeLeaf {
  1723. has Mu $!from;
  1724. method INIT(Mu \to, Mu \from) {
  1725. nqp::stmts(
  1726. ($!from := from),
  1727. self.SET-SELF(to)
  1728. )
  1729. }
  1730. method new(Mu \to, Mu \from) {
  1731. nqp::create(self).INIT(to,from)
  1732. }
  1733. method result(--> Nil) {
  1734. nqp::bindposnd_n($!list,$!indices,
  1735. nqp::multidimref_n($!from,$!indices))
  1736. }
  1737. }.new(to,from).sink-all;
  1738. to
  1739. }
  1740. sub OBJCPY(Mu \to, Mu \from) is raw {
  1741. class :: does Rakudo::Iterator::ShapeLeaf {
  1742. has Mu $!from;
  1743. method INIT(Mu \to, Mu \from) {
  1744. nqp::stmts(
  1745. ($!from := nqp::getattr(from,List,'$!reified')),
  1746. self.SET-SELF(to)
  1747. )
  1748. }
  1749. method new(Mu \to, Mu \from) {
  1750. nqp::create(self).INIT(to,from)
  1751. }
  1752. method result(--> Nil) {
  1753. nqp::bindposnd_n($!list,$!indices,
  1754. nqp::atposnd($!from,$!indices))
  1755. }
  1756. }.new(to,from).sink-all;
  1757. to
  1758. }
  1759. sub ITERCPY(Mu \to, Mu \from) is raw {
  1760. class :: does Rakudo::Iterator::ShapeBranch {
  1761. has $!iterators;
  1762. method INIT(\to,\from) {
  1763. nqp::stmts(
  1764. self.SET-SELF(to),
  1765. ($!iterators := nqp::setelems(
  1766. nqp::list(from.iterator),
  1767. nqp::add_i($!maxdim,1)
  1768. )),
  1769. self
  1770. )
  1771. }
  1772. method new(\to,\from) { nqp::create(self).INIT(to,from) }
  1773. method done(--> Nil) {
  1774. nqp::unless( # verify lowest
  1775. nqp::atpos($!iterators,0).is-lazy # finite iterator
  1776. || nqp::eqaddr( # and something there
  1777. nqp::atpos($!iterators,0).pull-one,IterationEnd),
  1778. nqp::atposnd_n($!list,$!indices) # boom!
  1779. )
  1780. }
  1781. method process(--> Nil) {
  1782. nqp::stmts(
  1783. (my int $i = $!level),
  1784. nqp::while(
  1785. nqp::isle_i(($i = nqp::add_i($i,1)),$!maxdim),
  1786. nqp::if(
  1787. nqp::eqaddr((my $item := # exhausted ?
  1788. nqp::atpos($!iterators,nqp::sub_i($i,1)).pull-one),
  1789. IterationEnd
  1790. ),
  1791. nqp::bindpos($!iterators,$i, # add an empty one
  1792. Rakudo::Iterator.Empty),
  1793. nqp::if( # is it an iterator?
  1794. nqp::istype($item,Iterable) && nqp::isconcrete($item),
  1795. nqp::bindpos($!iterators,$i,$item.iterator),
  1796. X::Assignment::ToShaped.new(shape => $!dims).throw
  1797. )
  1798. )
  1799. ),
  1800. (my $iter := nqp::atpos($!iterators,$!maxdim)),
  1801. nqp::until( # loop over highest dim
  1802. nqp::eqaddr((my $pulled := $iter.pull-one),IterationEnd)
  1803. || nqp::isgt_i(nqp::atpos_i($!indices,$!maxdim),$!maxind),
  1804. nqp::stmts(
  1805. nqp::bindposnd_n($!list,$!indices,$pulled),
  1806. nqp::bindpos_i($!indices,$!maxdim, # increment index
  1807. nqp::add_i(nqp::atpos_i($!indices,$!maxdim),1))
  1808. )
  1809. ),
  1810. nqp::unless(
  1811. nqp::eqaddr($pulled,IterationEnd) # if not exhausted
  1812. || nqp::isle_i( # and index too high
  1813. nqp::atpos_i($!indices,$!maxdim),$!maxind)
  1814. || $iter.is-lazy, # and not lazy
  1815. nqp::atposnd_n($!list,$!indices) # boom!
  1816. )
  1817. )
  1818. }
  1819. }.new(to,from).sink-all;
  1820. to
  1821. }
  1822. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  1823. nqp::if(
  1824. EQV_DIMENSIONS(self,from),
  1825. NATCPY(self,from),
  1826. X::Assignment::ArrayShapeMismatch.new(
  1827. source-shape => from.shape,
  1828. target-shape => self.shape
  1829. ).throw
  1830. )
  1831. }
  1832. multi method STORE(::?CLASS:D: array:D \from) {
  1833. nqp::if(
  1834. nqp::istype(from.of,Num),
  1835. nqp::if(
  1836. EQV_DIMENSIONS(self,from),
  1837. NATCPY(self,from),
  1838. X::Assignment::ArrayShapeMismatch.new(
  1839. source-shape => from.shape,
  1840. target-shape => self.shape
  1841. ).throw
  1842. ),
  1843. X::TypeCheck::Assignment.new(
  1844. symbol => self.^name ~ '[' ~ self.shape.join(';') ~ ']',
  1845. expected => Num,
  1846. got => from.of
  1847. ).throw
  1848. )
  1849. }
  1850. multi method STORE(::?CLASS:D: Iterable:D \from) {
  1851. nqp::if(
  1852. nqp::can(from,'shape'),
  1853. nqp::if(
  1854. from.shape eqv self.shape,
  1855. OBJCPY(self,from),
  1856. X::Assignment::ArrayShapeMismatch.new(
  1857. source-shape => from.shape,
  1858. target-shape => self.shape
  1859. ).throw
  1860. ),
  1861. ITERCPY(self,from)
  1862. )
  1863. }
  1864. method iterator(::?CLASS:D:) {
  1865. class :: does Rakudo::Iterator::ShapeLeaf {
  1866. method result() is raw {
  1867. nqp::multidimref_n($!list,nqp::clone($!indices))
  1868. }
  1869. }.new(self)
  1870. }
  1871. multi method kv(::?CLASS:D:) {
  1872. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  1873. has int $!on-key;
  1874. method result() is raw {
  1875. nqp::if(
  1876. ($!on-key = nqp::not_i($!on-key)),
  1877. nqp::stmts(
  1878. (my $result := self.indices),
  1879. (nqp::bindpos_i($!indices,$!maxdim, # back 1 for next
  1880. nqp::sub_i(nqp::atpos_i($!indices,$!maxdim),1))),
  1881. $result
  1882. ),
  1883. nqp::multidimref_n($!list,nqp::clone($!indices))
  1884. )
  1885. }
  1886. # needs its own push-all since it fiddles with $!indices
  1887. method push-all($target --> IterationEnd) {
  1888. nqp::until(
  1889. nqp::eqaddr((my $pulled := self.pull-one),IterationEnd),
  1890. $target.push($pulled)
  1891. )
  1892. }
  1893. }.new(self))
  1894. }
  1895. multi method pairs(::?CLASS:D:) {
  1896. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  1897. method result() {
  1898. Pair.new(
  1899. self.indices,
  1900. nqp::multidimref_n($!list,nqp::clone($!indices))
  1901. )
  1902. }
  1903. }.new(self))
  1904. }
  1905. multi method antipairs(::?CLASS:D:) {
  1906. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  1907. method result() {
  1908. Pair.new(nqp::atposnd_n($!list,$!indices),self.indices)
  1909. }
  1910. }.new(self))
  1911. }
  1912. } # end of shapednumarray role
  1913. role shaped1numarray does shapednumarray {
  1914. multi method AT-POS(::?CLASS:D: int \one) is raw {
  1915. nqp::atposref_n(self,one)
  1916. }
  1917. multi method AT-POS(::?CLASS:D: Int:D \one) is raw {
  1918. nqp::atposref_n(self,one)
  1919. }
  1920. multi method ASSIGN-POS(::?CLASS:D: int \one, num \value) {
  1921. nqp::bindpos_n(self,one,value)
  1922. }
  1923. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, num \value) {
  1924. nqp::bindpos_n(self,one,value)
  1925. }
  1926. multi method ASSIGN-POS(::?CLASS:D: int \one, Num:D \value) {
  1927. nqp::bindpos_n(self,one,value)
  1928. }
  1929. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Num:D \value) {
  1930. nqp::bindpos_n(self,one,value)
  1931. }
  1932. multi method EXISTS-POS(::?CLASS:D: int \one) {
  1933. nqp::p6bool(
  1934. nqp::isge_i(one,0) && nqp::islt_i(one,nqp::elems(self))
  1935. )
  1936. }
  1937. multi method EXISTS-POS(::?CLASS:D: Int:D \one) {
  1938. nqp::p6bool(
  1939. nqp::isge_i(one,0) && nqp::islt_i(one,nqp::elems(self))
  1940. )
  1941. }
  1942. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  1943. nqp::if(
  1944. nqp::iseq_i((my int $elems = nqp::elems(self)),nqp::elems(from)),
  1945. nqp::stmts(
  1946. (my int $i = -1),
  1947. nqp::while(
  1948. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  1949. nqp::bindpos_n(self,$i,nqp::atpos_n(from,$i))
  1950. ),
  1951. self
  1952. ),
  1953. X::Assignment::ArrayShapeMismatch.new(
  1954. source-shape => from.shape,
  1955. target-shape => self.shape
  1956. ).throw
  1957. )
  1958. }
  1959. multi method STORE(::?CLASS:D: Iterable:D \in) {
  1960. nqp::stmts(
  1961. (my \iter := in.iterator),
  1962. (my int $elems = nqp::elems(self)),
  1963. (my int $i = -1),
  1964. nqp::until(
  1965. nqp::eqaddr((my $pulled := iter.pull-one),IterationEnd)
  1966. || nqp::iseq_i(($i = nqp::add_i($i,1)),$elems),
  1967. nqp::bindpos_n(self,$i,$pulled)
  1968. ),
  1969. nqp::unless(
  1970. nqp::islt_i($i,$elems) || iter.is-lazy,
  1971. nqp::atpos_n(list,$i) # too many values on non-lazy it
  1972. ),
  1973. self
  1974. )
  1975. }
  1976. multi method STORE(::?CLASS:D: Num:D \item) {
  1977. nqp::stmts(
  1978. nqp::bindpos_n(self,0,item),
  1979. self
  1980. )
  1981. }
  1982. method iterator(::?CLASS:D:) {
  1983. class :: does Iterator {
  1984. has Mu $!list;
  1985. has int $!pos;
  1986. method !SET-SELF(Mu \list) {
  1987. nqp::stmts(
  1988. ($!list := list),
  1989. ($!pos = -1),
  1990. self
  1991. )
  1992. }
  1993. method new(Mu \list) { nqp::create(self)!SET-SELF(list) }
  1994. method pull-one() is raw {
  1995. nqp::if(
  1996. nqp::islt_i(
  1997. ($!pos = nqp::add_i($!pos,1)),
  1998. nqp::elems($!list)
  1999. ),
  2000. nqp::atposref_n($!list,$!pos),
  2001. IterationEnd
  2002. )
  2003. }
  2004. method push-all($target --> IterationEnd) {
  2005. nqp::stmts(
  2006. (my int $elems = nqp::elems($!list)),
  2007. (my int $i = -1),
  2008. nqp::while(
  2009. nqp::islt_i(($!pos = nqp::add_i($!pos,1)),$elems),
  2010. $target.push(nqp::atpos_n($!list,$!pos))
  2011. )
  2012. )
  2013. }
  2014. method count-only() { nqp::p6box_i(nqp::elems($!list)) }
  2015. method bool-only() { nqp::p6bool(nqp::elems($!list)) }
  2016. method sink-all(--> IterationEnd) {
  2017. $!pos = nqp::elems($!list)
  2018. }
  2019. }.new(self)
  2020. }
  2021. multi method kv(::?CLASS:D:) {
  2022. my int $i = -1;
  2023. my int $elems = nqp::add_i(nqp::elems(self),nqp::elems(self));
  2024. Seq.new(Rakudo::Iterator.Callable({
  2025. nqp::if(
  2026. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2027. nqp::if(
  2028. nqp::bitand_i($i,1),
  2029. nqp::atposref_n(self,nqp::bitshiftr_i($i,1)),
  2030. nqp::bitshiftr_i($i,1)
  2031. ),
  2032. IterationEnd
  2033. )
  2034. }))
  2035. }
  2036. multi method pairs(::?CLASS:D:) {
  2037. my int $i = -1;
  2038. my int $elems = nqp::elems(self);
  2039. Seq.new(Rakudo::Iterator.Callable({
  2040. nqp::if(
  2041. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2042. Pair.new($i,nqp::atposref_n(self,$i)),
  2043. IterationEnd
  2044. )
  2045. }))
  2046. }
  2047. multi method antipairs(::?CLASS:D:) {
  2048. Seq.new(Rakudo::Iterator.AntiPair(self.iterator))
  2049. }
  2050. method reverse(::?CLASS:D:) is nodal {
  2051. nqp::stmts(
  2052. (my int $elems = nqp::elems(self)),
  2053. (my int $last = nqp::sub_i($elems,1)),
  2054. (my int $i = -1),
  2055. (my $to := nqp::clone(self)),
  2056. nqp::while(
  2057. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2058. nqp::bindpos_n($to,nqp::sub_i($last,$i),
  2059. nqp::atpos_n(self,$i))
  2060. ),
  2061. $to
  2062. )
  2063. }
  2064. method rotate(::?CLASS:D: Int(Cool) $rotate = 1) is nodal {
  2065. nqp::stmts(
  2066. (my int $elems = nqp::elems(self)),
  2067. (my $to := nqp::clone(self)),
  2068. (my int $i = -1),
  2069. (my int $j =
  2070. nqp::mod_i(nqp::sub_i(nqp::sub_i($elems,1),$rotate),$elems)),
  2071. nqp::if(nqp::islt_i($j,0),($j = nqp::add_i($j,$elems))),
  2072. nqp::while(
  2073. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2074. nqp::bindpos_n(
  2075. $to,
  2076. ($j = nqp::mod_i(nqp::add_i($j,1),$elems)),
  2077. nqp::atpos_n(self,$i)
  2078. ),
  2079. ),
  2080. $to
  2081. )
  2082. }
  2083. } # end of shaped1numarray role
  2084. role shaped2numarray does shapednumarray {
  2085. multi method AT-POS(::?CLASS:D: int \one, int \two) is raw {
  2086. nqp::atpos2d_n(self,one,two)
  2087. }
  2088. multi method AT-POS(::?CLASS:D: Int:D \one, Int:D \two) is raw {
  2089. nqp::atpos2d_n(self,one,two)
  2090. }
  2091. multi method ASSIGN-POS(::?CLASS:D: int \one, int \two, Num:D \value) {
  2092. nqp::bindpos2d_n(self,one,two,value)
  2093. }
  2094. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \two, Num:D \value) {
  2095. nqp::bindpos2d_n(self,one,two,value)
  2096. }
  2097. multi method EXISTS-POS(::?CLASS:D: int \one, int \two) {
  2098. nqp::p6bool(
  2099. nqp::isge_i(one,0)
  2100. && nqp::isge_i(two,0)
  2101. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2102. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2103. )
  2104. }
  2105. multi method EXISTS-POS(::?CLASS:D: Int:D \one, Int:D \two) {
  2106. nqp::p6bool(
  2107. nqp::isge_i(one,0)
  2108. && nqp::isge_i(two,0)
  2109. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2110. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2111. )
  2112. }
  2113. } # end of shaped2numarray role
  2114. role shaped3numarray does shapednumarray {
  2115. multi method AT-POS(::?CLASS:D: int \one, int \two, int \three) is raw {
  2116. nqp::atpos3d_n(self,one,two,three)
  2117. }
  2118. multi method AT-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three) is raw {
  2119. nqp::atpos3d_n(self,one,two,three)
  2120. }
  2121. multi method ASSIGN-POS(::?CLASS:D: int \one, int \two, int \three, Num:D \value) {
  2122. nqp::bindpos3d_n(self,one,two,three,value)
  2123. }
  2124. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three, Num:D \value) {
  2125. nqp::bindpos3d_n(self,one,two,three,value)
  2126. }
  2127. multi method EXISTS-POS(::?CLASS:D: int \one, int \two, int \three) {
  2128. nqp::p6bool(
  2129. nqp::isge_i(one,0)
  2130. && nqp::isge_i(two,0)
  2131. && nqp::isge_i(three,0)
  2132. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2133. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2134. && nqp::islt_i(three,nqp::atpos_i(nqp::dimensions(self),2))
  2135. )
  2136. }
  2137. multi method EXISTS-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three) {
  2138. nqp::p6bool(
  2139. nqp::isge_i(one,0)
  2140. && nqp::isge_i(two,0)
  2141. && nqp::isge_i(three,0)
  2142. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2143. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2144. && nqp::islt_i(three,nqp::atpos_i(nqp::dimensions(self),2))
  2145. )
  2146. }
  2147. } # end of shaped3numarray role
  2148. #- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
  2149. #- end of generated part of shapednumarray role -------------------------------
  2150. #- start of generated part of shapedstrarray role -----------------------------
  2151. #- Generated on 2017-01-22T22:56:03+01:00 by tools/build/makeNATIVE_SHAPED_ARRAY.pl6
  2152. #- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
  2153. role shapedstrarray does shapedarray {
  2154. multi method AT-POS(::?CLASS:D: **@indices) is raw {
  2155. nqp::if(
  2156. nqp::iseq_i(
  2157. (my int $numdims = nqp::numdimensions(self)),
  2158. (my int $numind = @indices.elems), # reifies
  2159. ),
  2160. nqp::stmts(
  2161. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  2162. (my $idxs := nqp::list_i),
  2163. nqp::while( # native index list
  2164. nqp::isge_i(($numdims = nqp::sub_i($numdims,1)),0),
  2165. nqp::push_i($idxs,nqp::shift($indices))
  2166. ),
  2167. nqp::multidimref_s(self,$idxs)
  2168. ),
  2169. nqp::if(
  2170. nqp::isgt_i($numind,$numdims),
  2171. X::TooManyDimensions.new(
  2172. operation => 'access',
  2173. got-dimensions => $numind,
  2174. needed-dimensions => $numdims
  2175. ).throw,
  2176. X::NYI.new(
  2177. feature => "Partially dimensioned views of shaped arrays"
  2178. ).throw
  2179. )
  2180. )
  2181. }
  2182. multi method ASSIGN-POS(::?CLASS:D: **@indices) {
  2183. nqp::stmts(
  2184. (my str $value = @indices.pop),
  2185. nqp::if(
  2186. nqp::iseq_i(
  2187. (my int $numdims = nqp::numdimensions(self)),
  2188. (my int $numind = @indices.elems), # reifies
  2189. ),
  2190. nqp::stmts(
  2191. (my $indices := nqp::getattr(@indices,List,'$!reified')),
  2192. (my $idxs := nqp::list_i),
  2193. nqp::while( # native index list
  2194. nqp::isge_i(($numdims = nqp::sub_i($numdims,1)),0),
  2195. nqp::push_i($idxs,nqp::shift($indices))
  2196. ),
  2197. nqp::bindposnd_s(self, $idxs, $value)
  2198. ),
  2199. nqp::if(
  2200. nqp::isgt_i($numind,$numdims),
  2201. X::TooManyDimensions,
  2202. X::NotEnoughDimensions
  2203. ).new(
  2204. operation => 'assign to',
  2205. got-dimensions => $numind,
  2206. needed-dimensions => $numdims
  2207. ).throw
  2208. )
  2209. )
  2210. }
  2211. sub NATCPY(Mu \to, Mu \from) is raw {
  2212. class :: does Rakudo::Iterator::ShapeLeaf {
  2213. has Mu $!from;
  2214. method INIT(Mu \to, Mu \from) {
  2215. nqp::stmts(
  2216. ($!from := from),
  2217. self.SET-SELF(to)
  2218. )
  2219. }
  2220. method new(Mu \to, Mu \from) {
  2221. nqp::create(self).INIT(to,from)
  2222. }
  2223. method result(--> Nil) {
  2224. nqp::bindposnd_s($!list,$!indices,
  2225. nqp::multidimref_s($!from,$!indices))
  2226. }
  2227. }.new(to,from).sink-all;
  2228. to
  2229. }
  2230. sub OBJCPY(Mu \to, Mu \from) is raw {
  2231. class :: does Rakudo::Iterator::ShapeLeaf {
  2232. has Mu $!from;
  2233. method INIT(Mu \to, Mu \from) {
  2234. nqp::stmts(
  2235. ($!from := nqp::getattr(from,List,'$!reified')),
  2236. self.SET-SELF(to)
  2237. )
  2238. }
  2239. method new(Mu \to, Mu \from) {
  2240. nqp::create(self).INIT(to,from)
  2241. }
  2242. method result(--> Nil) {
  2243. nqp::bindposnd_s($!list,$!indices,
  2244. nqp::atposnd($!from,$!indices))
  2245. }
  2246. }.new(to,from).sink-all;
  2247. to
  2248. }
  2249. sub ITERCPY(Mu \to, Mu \from) is raw {
  2250. class :: does Rakudo::Iterator::ShapeBranch {
  2251. has $!iterators;
  2252. method INIT(\to,\from) {
  2253. nqp::stmts(
  2254. self.SET-SELF(to),
  2255. ($!iterators := nqp::setelems(
  2256. nqp::list(from.iterator),
  2257. nqp::add_i($!maxdim,1)
  2258. )),
  2259. self
  2260. )
  2261. }
  2262. method new(\to,\from) { nqp::create(self).INIT(to,from) }
  2263. method done(--> Nil) {
  2264. nqp::unless( # verify lowest
  2265. nqp::atpos($!iterators,0).is-lazy # finite iterator
  2266. || nqp::eqaddr( # and something there
  2267. nqp::atpos($!iterators,0).pull-one,IterationEnd),
  2268. nqp::atposnd_s($!list,$!indices) # boom!
  2269. )
  2270. }
  2271. method process(--> Nil) {
  2272. nqp::stmts(
  2273. (my int $i = $!level),
  2274. nqp::while(
  2275. nqp::isle_i(($i = nqp::add_i($i,1)),$!maxdim),
  2276. nqp::if(
  2277. nqp::eqaddr((my $item := # exhausted ?
  2278. nqp::atpos($!iterators,nqp::sub_i($i,1)).pull-one),
  2279. IterationEnd
  2280. ),
  2281. nqp::bindpos($!iterators,$i, # add an empty one
  2282. Rakudo::Iterator.Empty),
  2283. nqp::if( # is it an iterator?
  2284. nqp::istype($item,Iterable) && nqp::isconcrete($item),
  2285. nqp::bindpos($!iterators,$i,$item.iterator),
  2286. X::Assignment::ToShaped.new(shape => $!dims).throw
  2287. )
  2288. )
  2289. ),
  2290. (my $iter := nqp::atpos($!iterators,$!maxdim)),
  2291. nqp::until( # loop over highest dim
  2292. nqp::eqaddr((my $pulled := $iter.pull-one),IterationEnd)
  2293. || nqp::isgt_i(nqp::atpos_i($!indices,$!maxdim),$!maxind),
  2294. nqp::stmts(
  2295. nqp::bindposnd_s($!list,$!indices,$pulled),
  2296. nqp::bindpos_i($!indices,$!maxdim, # increment index
  2297. nqp::add_i(nqp::atpos_i($!indices,$!maxdim),1))
  2298. )
  2299. ),
  2300. nqp::unless(
  2301. nqp::eqaddr($pulled,IterationEnd) # if not exhausted
  2302. || nqp::isle_i( # and index too high
  2303. nqp::atpos_i($!indices,$!maxdim),$!maxind)
  2304. || $iter.is-lazy, # and not lazy
  2305. nqp::atposnd_s($!list,$!indices) # boom!
  2306. )
  2307. )
  2308. }
  2309. }.new(to,from).sink-all;
  2310. to
  2311. }
  2312. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  2313. nqp::if(
  2314. EQV_DIMENSIONS(self,from),
  2315. NATCPY(self,from),
  2316. X::Assignment::ArrayShapeMismatch.new(
  2317. source-shape => from.shape,
  2318. target-shape => self.shape
  2319. ).throw
  2320. )
  2321. }
  2322. multi method STORE(::?CLASS:D: array:D \from) {
  2323. nqp::if(
  2324. nqp::istype(from.of,Str),
  2325. nqp::if(
  2326. EQV_DIMENSIONS(self,from),
  2327. NATCPY(self,from),
  2328. X::Assignment::ArrayShapeMismatch.new(
  2329. source-shape => from.shape,
  2330. target-shape => self.shape
  2331. ).throw
  2332. ),
  2333. X::TypeCheck::Assignment.new(
  2334. symbol => self.^name ~ '[' ~ self.shape.join(';') ~ ']',
  2335. expected => Str,
  2336. got => from.of
  2337. ).throw
  2338. )
  2339. }
  2340. multi method STORE(::?CLASS:D: Iterable:D \from) {
  2341. nqp::if(
  2342. nqp::can(from,'shape'),
  2343. nqp::if(
  2344. from.shape eqv self.shape,
  2345. OBJCPY(self,from),
  2346. X::Assignment::ArrayShapeMismatch.new(
  2347. source-shape => from.shape,
  2348. target-shape => self.shape
  2349. ).throw
  2350. ),
  2351. ITERCPY(self,from)
  2352. )
  2353. }
  2354. method iterator(::?CLASS:D:) {
  2355. class :: does Rakudo::Iterator::ShapeLeaf {
  2356. method result() is raw {
  2357. nqp::multidimref_s($!list,nqp::clone($!indices))
  2358. }
  2359. }.new(self)
  2360. }
  2361. multi method kv(::?CLASS:D:) {
  2362. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  2363. has int $!on-key;
  2364. method result() is raw {
  2365. nqp::if(
  2366. ($!on-key = nqp::not_i($!on-key)),
  2367. nqp::stmts(
  2368. (my $result := self.indices),
  2369. (nqp::bindpos_i($!indices,$!maxdim, # back 1 for next
  2370. nqp::sub_i(nqp::atpos_i($!indices,$!maxdim),1))),
  2371. $result
  2372. ),
  2373. nqp::multidimref_s($!list,nqp::clone($!indices))
  2374. )
  2375. }
  2376. # needs its own push-all since it fiddles with $!indices
  2377. method push-all($target --> IterationEnd) {
  2378. nqp::until(
  2379. nqp::eqaddr((my $pulled := self.pull-one),IterationEnd),
  2380. $target.push($pulled)
  2381. )
  2382. }
  2383. }.new(self))
  2384. }
  2385. multi method pairs(::?CLASS:D:) {
  2386. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  2387. method result() {
  2388. Pair.new(
  2389. self.indices,
  2390. nqp::multidimref_s($!list,nqp::clone($!indices))
  2391. )
  2392. }
  2393. }.new(self))
  2394. }
  2395. multi method antipairs(::?CLASS:D:) {
  2396. Seq.new(class :: does Rakudo::Iterator::ShapeLeaf {
  2397. method result() {
  2398. Pair.new(nqp::atposnd_s($!list,$!indices),self.indices)
  2399. }
  2400. }.new(self))
  2401. }
  2402. } # end of shapedstrarray role
  2403. role shaped1strarray does shapedstrarray {
  2404. multi method AT-POS(::?CLASS:D: int \one) is raw {
  2405. nqp::atposref_s(self,one)
  2406. }
  2407. multi method AT-POS(::?CLASS:D: Int:D \one) is raw {
  2408. nqp::atposref_s(self,one)
  2409. }
  2410. multi method ASSIGN-POS(::?CLASS:D: int \one, str \value) {
  2411. nqp::bindpos_s(self,one,value)
  2412. }
  2413. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, str \value) {
  2414. nqp::bindpos_s(self,one,value)
  2415. }
  2416. multi method ASSIGN-POS(::?CLASS:D: int \one, Str:D \value) {
  2417. nqp::bindpos_s(self,one,value)
  2418. }
  2419. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Str:D \value) {
  2420. nqp::bindpos_s(self,one,value)
  2421. }
  2422. multi method EXISTS-POS(::?CLASS:D: int \one) {
  2423. nqp::p6bool(
  2424. nqp::isge_i(one,0) && nqp::islt_i(one,nqp::elems(self))
  2425. )
  2426. }
  2427. multi method EXISTS-POS(::?CLASS:D: Int:D \one) {
  2428. nqp::p6bool(
  2429. nqp::isge_i(one,0) && nqp::islt_i(one,nqp::elems(self))
  2430. )
  2431. }
  2432. multi method STORE(::?CLASS:D: ::?CLASS:D \from) {
  2433. nqp::if(
  2434. nqp::iseq_i((my int $elems = nqp::elems(self)),nqp::elems(from)),
  2435. nqp::stmts(
  2436. (my int $i = -1),
  2437. nqp::while(
  2438. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2439. nqp::bindpos_s(self,$i,nqp::atpos_s(from,$i))
  2440. ),
  2441. self
  2442. ),
  2443. X::Assignment::ArrayShapeMismatch.new(
  2444. source-shape => from.shape,
  2445. target-shape => self.shape
  2446. ).throw
  2447. )
  2448. }
  2449. multi method STORE(::?CLASS:D: Iterable:D \in) {
  2450. nqp::stmts(
  2451. (my \iter := in.iterator),
  2452. (my int $elems = nqp::elems(self)),
  2453. (my int $i = -1),
  2454. nqp::until(
  2455. nqp::eqaddr((my $pulled := iter.pull-one),IterationEnd)
  2456. || nqp::iseq_i(($i = nqp::add_i($i,1)),$elems),
  2457. nqp::bindpos_s(self,$i,$pulled)
  2458. ),
  2459. nqp::unless(
  2460. nqp::islt_i($i,$elems) || iter.is-lazy,
  2461. nqp::atpos_s(list,$i) # too many values on non-lazy it
  2462. ),
  2463. self
  2464. )
  2465. }
  2466. multi method STORE(::?CLASS:D: Str:D \item) {
  2467. nqp::stmts(
  2468. nqp::bindpos_s(self,0,item),
  2469. self
  2470. )
  2471. }
  2472. method iterator(::?CLASS:D:) {
  2473. class :: does Iterator {
  2474. has Mu $!list;
  2475. has int $!pos;
  2476. method !SET-SELF(Mu \list) {
  2477. nqp::stmts(
  2478. ($!list := list),
  2479. ($!pos = -1),
  2480. self
  2481. )
  2482. }
  2483. method new(Mu \list) { nqp::create(self)!SET-SELF(list) }
  2484. method pull-one() is raw {
  2485. nqp::if(
  2486. nqp::islt_i(
  2487. ($!pos = nqp::add_i($!pos,1)),
  2488. nqp::elems($!list)
  2489. ),
  2490. nqp::atposref_s($!list,$!pos),
  2491. IterationEnd
  2492. )
  2493. }
  2494. method push-all($target --> IterationEnd) {
  2495. nqp::stmts(
  2496. (my int $elems = nqp::elems($!list)),
  2497. (my int $i = -1),
  2498. nqp::while(
  2499. nqp::islt_i(($!pos = nqp::add_i($!pos,1)),$elems),
  2500. $target.push(nqp::atpos_s($!list,$!pos))
  2501. )
  2502. )
  2503. }
  2504. method count-only() { nqp::p6box_i(nqp::elems($!list)) }
  2505. method bool-only() { nqp::p6bool(nqp::elems($!list)) }
  2506. method sink-all(--> IterationEnd) {
  2507. $!pos = nqp::elems($!list)
  2508. }
  2509. }.new(self)
  2510. }
  2511. multi method kv(::?CLASS:D:) {
  2512. my int $i = -1;
  2513. my int $elems = nqp::add_i(nqp::elems(self),nqp::elems(self));
  2514. Seq.new(Rakudo::Iterator.Callable({
  2515. nqp::if(
  2516. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2517. nqp::if(
  2518. nqp::bitand_i($i,1),
  2519. nqp::atposref_s(self,nqp::bitshiftr_i($i,1)),
  2520. nqp::bitshiftr_i($i,1)
  2521. ),
  2522. IterationEnd
  2523. )
  2524. }))
  2525. }
  2526. multi method pairs(::?CLASS:D:) {
  2527. my int $i = -1;
  2528. my int $elems = nqp::elems(self);
  2529. Seq.new(Rakudo::Iterator.Callable({
  2530. nqp::if(
  2531. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2532. Pair.new($i,nqp::atposref_s(self,$i)),
  2533. IterationEnd
  2534. )
  2535. }))
  2536. }
  2537. multi method antipairs(::?CLASS:D:) {
  2538. Seq.new(Rakudo::Iterator.AntiPair(self.iterator))
  2539. }
  2540. method reverse(::?CLASS:D:) is nodal {
  2541. nqp::stmts(
  2542. (my int $elems = nqp::elems(self)),
  2543. (my int $last = nqp::sub_i($elems,1)),
  2544. (my int $i = -1),
  2545. (my $to := nqp::clone(self)),
  2546. nqp::while(
  2547. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2548. nqp::bindpos_s($to,nqp::sub_i($last,$i),
  2549. nqp::atpos_s(self,$i))
  2550. ),
  2551. $to
  2552. )
  2553. }
  2554. method rotate(::?CLASS:D: Int(Cool) $rotate = 1) is nodal {
  2555. nqp::stmts(
  2556. (my int $elems = nqp::elems(self)),
  2557. (my $to := nqp::clone(self)),
  2558. (my int $i = -1),
  2559. (my int $j =
  2560. nqp::mod_i(nqp::sub_i(nqp::sub_i($elems,1),$rotate),$elems)),
  2561. nqp::if(nqp::islt_i($j,0),($j = nqp::add_i($j,$elems))),
  2562. nqp::while(
  2563. nqp::islt_i(($i = nqp::add_i($i,1)),$elems),
  2564. nqp::bindpos_s(
  2565. $to,
  2566. ($j = nqp::mod_i(nqp::add_i($j,1),$elems)),
  2567. nqp::atpos_s(self,$i)
  2568. ),
  2569. ),
  2570. $to
  2571. )
  2572. }
  2573. } # end of shaped1strarray role
  2574. role shaped2strarray does shapedstrarray {
  2575. multi method AT-POS(::?CLASS:D: int \one, int \two) is raw {
  2576. nqp::atpos2d_s(self,one,two)
  2577. }
  2578. multi method AT-POS(::?CLASS:D: Int:D \one, Int:D \two) is raw {
  2579. nqp::atpos2d_s(self,one,two)
  2580. }
  2581. multi method ASSIGN-POS(::?CLASS:D: int \one, int \two, Str:D \value) {
  2582. nqp::bindpos2d_s(self,one,two,value)
  2583. }
  2584. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \two, Str:D \value) {
  2585. nqp::bindpos2d_s(self,one,two,value)
  2586. }
  2587. multi method EXISTS-POS(::?CLASS:D: int \one, int \two) {
  2588. nqp::p6bool(
  2589. nqp::isge_i(one,0)
  2590. && nqp::isge_i(two,0)
  2591. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2592. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2593. )
  2594. }
  2595. multi method EXISTS-POS(::?CLASS:D: Int:D \one, Int:D \two) {
  2596. nqp::p6bool(
  2597. nqp::isge_i(one,0)
  2598. && nqp::isge_i(two,0)
  2599. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2600. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2601. )
  2602. }
  2603. } # end of shaped2strarray role
  2604. role shaped3strarray does shapedstrarray {
  2605. multi method AT-POS(::?CLASS:D: int \one, int \two, int \three) is raw {
  2606. nqp::atpos3d_s(self,one,two,three)
  2607. }
  2608. multi method AT-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three) is raw {
  2609. nqp::atpos3d_s(self,one,two,three)
  2610. }
  2611. multi method ASSIGN-POS(::?CLASS:D: int \one, int \two, int \three, Str:D \value) {
  2612. nqp::bindpos3d_s(self,one,two,three,value)
  2613. }
  2614. multi method ASSIGN-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three, Str:D \value) {
  2615. nqp::bindpos3d_s(self,one,two,three,value)
  2616. }
  2617. multi method EXISTS-POS(::?CLASS:D: int \one, int \two, int \three) {
  2618. nqp::p6bool(
  2619. nqp::isge_i(one,0)
  2620. && nqp::isge_i(two,0)
  2621. && nqp::isge_i(three,0)
  2622. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2623. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2624. && nqp::islt_i(three,nqp::atpos_i(nqp::dimensions(self),2))
  2625. )
  2626. }
  2627. multi method EXISTS-POS(::?CLASS:D: Int:D \one, Int:D \two, Int:D \three) {
  2628. nqp::p6bool(
  2629. nqp::isge_i(one,0)
  2630. && nqp::isge_i(two,0)
  2631. && nqp::isge_i(three,0)
  2632. && nqp::islt_i(one,nqp::atpos_i(nqp::dimensions(self),0))
  2633. && nqp::islt_i(two,nqp::atpos_i(nqp::dimensions(self),1))
  2634. && nqp::islt_i(three,nqp::atpos_i(nqp::dimensions(self),2))
  2635. )
  2636. }
  2637. } # end of shaped3strarray role
  2638. #- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
  2639. #- end of generated part of shapedstrarray role -------------------------------
  2640. method ^parameterize(Mu:U \arr, Mu:U \t) {
  2641. my $t := nqp::decont(t);
  2642. my int $kind = nqp::objprimspec($t);
  2643. my $what;
  2644. if $kind == 1 {
  2645. $what := arr.^mixin(intarray[$t]);
  2646. }
  2647. elsif $kind == 2 {
  2648. $what := arr.^mixin(numarray[$t]);
  2649. }
  2650. elsif $kind == 3 {
  2651. $what := arr.^mixin(strarray[$t]);
  2652. }
  2653. else {
  2654. die "Can only parameterize array with a native type, not {t.^name}";
  2655. }
  2656. $what.^set_name("{arr.^name}[{t.^name}]");
  2657. $what;
  2658. }
  2659. # poor man's 3x4 matrix
  2660. constant typedim2role := nqp::list(nqp::null,
  2661. nqp::list(shapedintarray,shaped1intarray,shaped2intarray,shaped3intarray),
  2662. nqp::list(shapednumarray,shaped1numarray,shaped2numarray,shaped3numarray),
  2663. nqp::list(shapedstrarray,shaped1strarray,shaped2strarray,shaped3strarray)
  2664. );
  2665. method !shaped(\shape) {
  2666. nqp::if(
  2667. (my int $dims = shape.elems), # reifies
  2668. nqp::stmts(
  2669. # Calculate new meta-object (probably hitting caches in most cases).
  2670. (my \shaped-type = self.WHAT.^mixin(
  2671. nqp::atpos(
  2672. nqp::atpos(typedim2role,nqp::objprimspec(my \T = self.of)),
  2673. nqp::isle_i($dims,3) && $dims
  2674. )
  2675. )),
  2676. nqp::if( # set name if needed
  2677. nqp::isne_s(shaped-type.^name,self.WHAT.^name),
  2678. shaped-type.^set_name(self.WHAT.^name)
  2679. ),
  2680. # Allocate array storage for this shape, based on calculated type.
  2681. Rakudo::Internals.SHAPED-ARRAY-STORAGE(shape,shaped-type.HOW,T)
  2682. ),
  2683. X::NotEnoughDimensions.new(
  2684. operation => 'create',
  2685. got-dimensions => $dims,
  2686. needed-dimensions => '',
  2687. ).throw
  2688. )
  2689. }
  2690. method BIND-POS(|) {
  2691. die "Cannot bind to a natively typed array";
  2692. }
  2693. method DELETE-POS(|) {
  2694. die "Cannot delete from a natively typed array";
  2695. }
  2696. proto method ASSIGN-POS(|) { * } # Hide candidates from Any
  2697. multi method ASSIGN-POS(Any:U \SELF: \pos, Mu \assignee) { # auto-viv
  2698. SELF.AT-POS(pos) = assignee;
  2699. }
  2700. multi method ASSIGN-POS(Any:D: Any:U \pos, Mu \assignee) { # undefined idx
  2701. die "Cannot use '{pos.^name}' as an index";
  2702. }
  2703. multi method EXISTS-POS(array:D: int $idx) {
  2704. $idx >= 0 && $idx < nqp::elems(self)
  2705. }
  2706. multi method EXISTS-POS(array:D: Int $idx) {
  2707. $idx >= 0 && $idx < nqp::elems(self)
  2708. }
  2709. multi method Bool(array:D:) { nqp::p6bool(nqp::elems(self)) }
  2710. multi method Numeric(array:D:) { nqp::elems(self) }
  2711. multi method Str(array:D:) { self.join(' ') }
  2712. multi method elems(array:D:) { nqp::elems(self) }
  2713. method shape() { (*,) }
  2714. proto method Int(|) { * }
  2715. multi method Int(array:D:) { nqp::elems(self) }
  2716. multi method end(array:D:) { nqp::elems(self) - 1 }
  2717. method eager() { self }
  2718. method flat() { Seq.new(self.iterator) }
  2719. method list() { List.from-iterator(self.iterator) }
  2720. method sink(--> Nil) { }
  2721. multi method gist(array:D:) {
  2722. self.map(-> $elem {
  2723. given ++$ {
  2724. when 101 { '...' }
  2725. when 102 { last }
  2726. default { $elem.gist }
  2727. }
  2728. } ).join: ' ';
  2729. }
  2730. multi method perl(array:D:) {
  2731. 'array[' ~ self.of.perl ~ '].new(' ~
  2732. self.map(*.perl).join(', ') ~ ')'
  2733. }
  2734. method FLATTENABLE_LIST() { self }
  2735. method FLATTENABLE_HASH() { nqp::hash() }
  2736. method iterator() {
  2737. nqp::die('iterator must be provided by native array parameterization role')
  2738. }
  2739. }