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