1. my class Pair { ... }
  2. my class Range { ... }
  3. my class X::Adverb { ... }
  4. my class X::Bind { ... }
  5. my class X::Bind::Slice { ... }
  6. my class X::Bind::ZenSlice { ... }
  7. my class X::Item { ... }
  8. my class X::Match::Bool { ... }
  9. my class X::Pairup::OddNumber { ... }
  10. my class X::Subscript::Negative { ... }
  11. my role Numeric { ... }
  12. my class Any { # declared in BOOTSTRAP
  13. # my class Any is Mu
  14. multi method ACCEPTS(Any:D: Mu:D \a) { self === a }
  15. multi method ACCEPTS(Any:D: Mu:U $ --> False) { }
  16. multi method ACCEPTS(Any:U: Any \topic) { # use of Any on topic to force autothreading
  17. nqp::p6bool(nqp::istype(topic, self)) # so that all(@foo) ~~ Type works as expected
  18. }
  19. proto method EXISTS-KEY(|) is nodal { * }
  20. multi method EXISTS-KEY(Any:U: $ --> False) { }
  21. multi method EXISTS-KEY(Any:D: $ --> False) { }
  22. proto method DELETE-KEY(|) is nodal { * }
  23. multi method DELETE-KEY(Any:U: $ --> Nil) { }
  24. multi method DELETE-KEY(Any:D: $) {
  25. Failure.new("Can not remove values from a {self.^name}")
  26. }
  27. proto method DELETE-POS(|) is nodal { * }
  28. multi method DELETE-POS(Any:U: $pos --> Nil) { }
  29. multi method DELETE-POS(Any:D: $pos) {
  30. Failure.new("Can not remove elements from a {self.^name}")
  31. }
  32. multi method DELETE-POS(Any:D: \one, \two) is raw {
  33. self.AT-POS(one).DELETE-POS(two)
  34. }
  35. multi method DELETE-POS(Any:D: \one, \two, \three) is raw {
  36. self.AT-POS(one).AT-POS(two).DELETE-POS(three)
  37. }
  38. multi method DELETE-POS(Any:D: **@indices) {
  39. my $final := @indices.pop;
  40. Rakudo::Internals.WALK-AT-POS(self,@indices).DELETE-POS($final)
  41. }
  42. method cache() { self.list }
  43. proto method list(|) is nodal { * }
  44. multi method list(Any:U:) { infix:<,>(self) }
  45. multi method list(Any:D \SELF:) { infix:<,>(SELF) }
  46. proto method flat(|) is nodal { * }
  47. multi method flat() { self.list.flat }
  48. proto method eager(|) is nodal { * }
  49. multi method eager() { self.list.eager }
  50. # derived from .list
  51. proto method List(|) is nodal { * }
  52. multi method List() { self.list }
  53. proto method Slip(|) is nodal { * }
  54. multi method Slip() { self.list.Slip }
  55. proto method Array(|) is nodal { * }
  56. multi method Array() { self.list.Array }
  57. proto method hash(|) is nodal { * }
  58. multi method hash(Any:U:) { my % = () }
  59. multi method hash(Any:D:) { my % = self }
  60. # derived from .hash
  61. proto method Hash(|) is nodal { * }
  62. multi method Hash() { self.hash.Hash }
  63. proto method Map(|) is nodal { * }
  64. multi method Map() { self.hash.Map }
  65. proto method elems(|) is nodal { * }
  66. multi method elems(Any:U: --> 1) { }
  67. multi method elems(Any:D:) { self.list.elems }
  68. proto method end(|) is nodal { * }
  69. multi method end(Any:U: --> 0) { }
  70. multi method end(Any:D:) { self.list.end }
  71. proto method keys(|) is nodal { * }
  72. multi method keys(Any:U:) { () }
  73. multi method keys(Any:D:) { self.list.keys }
  74. proto method kv(|) is nodal { * }
  75. multi method kv(Any:U:) { () }
  76. multi method kv(Any:D:) { self.list.kv }
  77. proto method values(|) is nodal { * }
  78. multi method values(Any:U:) { () }
  79. multi method values(Any:D:) { self.list }
  80. proto method pairs(|) is nodal { * }
  81. multi method pairs(Any:U:) { () }
  82. multi method pairs(Any:D:) { self.list.pairs }
  83. proto method antipairs(|) is nodal { * }
  84. multi method antipairs(Any:U:) { () }
  85. multi method antipairs(Any:D:) { self.list.antipairs }
  86. proto method invert(|) is nodal { * }
  87. multi method invert(Any:U:) { () }
  88. multi method invert(Any:D:) { self.list.invert }
  89. proto method pick(|) is nodal { * }
  90. multi method pick() { self.list.pick }
  91. multi method pick($n) { self.list.pick($n) }
  92. proto method roll(|) is nodal { * }
  93. multi method roll() { self.list.roll }
  94. multi method roll($n) { self.list.roll($n) }
  95. multi method iterator(Any:) { self.list.iterator }
  96. method match(Any:U: |) { self.Str; nqp::getlexcaller('$/') = Nil }
  97. proto method classify(|) is nodal { * }
  98. multi method classify() {
  99. die "Must specify something to classify with, a Callable, Hash or List";
  100. }
  101. multi method classify(Whatever) {
  102. die "Doesn't make sense to classify with itself";
  103. }
  104. multi method classify($test, :$into!, :&as) {
  105. ( $into // $into.new ).classify-list( $test, self, :&as);
  106. }
  107. multi method classify($test, :&as) {
  108. Hash.^parameterize(Any,Any).new.classify-list( $test, self, :&as );
  109. }
  110. proto method categorize(|) is nodal { * }
  111. multi method categorize() {
  112. die "Must specify something to categorize with, a Callable, Hash or List";
  113. }
  114. multi method categorize(Whatever) {
  115. die "Doesn't make sense to categorize with itself";
  116. }
  117. multi method categorize($test, :$into!, :&as) {
  118. ( $into // $into.new ).categorize-list( $test, self.list, :&as );
  119. }
  120. multi method categorize($test, :&as) {
  121. Hash.^parameterize(Any,Any).new.categorize-list($test, self.list, :&as);
  122. }
  123. method reverse() is nodal { self.list.reverse }
  124. method combinations(|c) is nodal { self.list.combinations(|c) }
  125. method permutations(|c) is nodal { self.list.permutations(|c) }
  126. method join($separator = '') is nodal { self.list.join($separator) }
  127. # XXX GLR should move these
  128. method nodemap(&block) is nodal { nodemap(&block, self) }
  129. method duckmap(&block) is nodal { duckmap(&block, self) }
  130. method deepmap(&block) is nodal { deepmap(&block, self) }
  131. # XXX GLR Do we need tree post-GLR?
  132. proto method tree(|) is nodal { * }
  133. multi method tree(Any:U:) { self }
  134. multi method tree(Any:D:) {
  135. nqp::istype(self, Iterable)
  136. ?? self.map({ .tree }).item
  137. !! self
  138. }
  139. multi method tree(Any:D: Whatever ) { self.tree }
  140. multi method tree(Any:D: Int(Cool) $count) {
  141. nqp::istype(self, Iterable) && $count > 0
  142. ?? self.map({ .tree($count - 1) }).item
  143. !! self
  144. }
  145. multi method tree(Any:D: @ [&first, *@rest]) { self.tree(&first, |@rest); }
  146. multi method tree(Any:D: &first, *@rest) {
  147. nqp::istype(self, Iterable)
  148. ?? @rest ?? first(self.map({ .tree(|@rest) }))
  149. !! first(self)
  150. !! self
  151. }
  152. # auto-vivifying
  153. proto method push(|) is nodal {*}
  154. multi method push(Any:U \SELF: |values) {
  155. SELF = nqp::istype(SELF,Positional) ?? SELF.new !! Array.new;
  156. SELF.push(|values);
  157. }
  158. proto method append(|) is nodal { * }
  159. multi method append(Any:U \SELF: |values) {
  160. SELF = nqp::istype(SELF,Positional) ?? SELF.new !! Array.new;
  161. SELF.append(|values);
  162. }
  163. proto method unshift(|) is nodal { * }
  164. multi method unshift(Any:U \SELF: |values) {
  165. SELF = Array.new;
  166. SELF.unshift(|values);
  167. }
  168. proto method prepend(|) is nodal { * }
  169. multi method prepend(Any:U \SELF: |values) {
  170. SELF = Array.new;
  171. SELF.prepend(|values);
  172. }
  173. proto method EXISTS-POS(|) is nodal { * }
  174. multi method EXISTS-POS(Any:U: Any:D $ --> False) { }
  175. multi method EXISTS-POS(Any:U: Any:U $pos) {
  176. die "Cannot use '{$pos.^name}' as an index";
  177. }
  178. multi method EXISTS-POS(Any:D: int \pos) {
  179. nqp::p6bool(nqp::iseq_i(pos,0));
  180. }
  181. multi method EXISTS-POS(Any:D: Int:D \pos) {
  182. pos == 0;
  183. }
  184. multi method EXISTS-POS(Any:D: Num:D \pos) {
  185. X::Item.new(aggregate => self, index => pos).throw
  186. if nqp::isnanorinf(pos);
  187. self.AT-POS(nqp::unbox_i(pos.Int));
  188. pos == 0;
  189. }
  190. multi method EXISTS-POS(Any:D: Any:D \pos) {
  191. pos.Int == 0;
  192. }
  193. multi method EXISTS-POS(Any:D: Any:U \pos) {
  194. die "Cannot use '{pos.^name}' as an index";
  195. }
  196. multi method EXISTS-POS(Any:D: \one, \two) is raw {
  197. self.AT-POS(one).EXISTS-POS(two)
  198. }
  199. multi method EXISTS-POS(Any:D: \one, \two,\three) is raw {
  200. self.AT-POS(one).AT-POS(two).EXISTS-POS(three)
  201. }
  202. multi method EXISTS-POS(Any:D: **@indices) {
  203. my $final := @indices.pop;
  204. Rakudo::Internals.WALK-AT-POS(self,@indices).EXISTS-POS($final)
  205. }
  206. proto method AT-POS(|) is nodal {*}
  207. multi method AT-POS(Any:U \SELF: int \pos) is raw {
  208. nqp::p6bindattrinvres(
  209. my $scalar,
  210. Scalar,
  211. '$!whence',
  212. -> { nqp::if(
  213. nqp::isconcrete(SELF),
  214. SELF,
  215. (SELF = Array.new)
  216. ).BIND-POS(pos, $scalar)
  217. }
  218. )
  219. }
  220. multi method AT-POS(Any:U \SELF: Int:D \pos) is raw {
  221. nqp::p6bindattrinvres(
  222. my $scalar,
  223. Scalar,
  224. '$!whence',
  225. -> { nqp::if(
  226. nqp::isconcrete(SELF),
  227. SELF,
  228. (SELF = Array.new)
  229. ).BIND-POS(pos, $scalar)
  230. }
  231. )
  232. }
  233. multi method AT-POS(Any:U: Num:D \pos) is raw {
  234. nqp::isnanorinf(pos)
  235. ?? Failure.new(X::Item.new(aggregate => self, index => pos))
  236. !! self.AT-POS(nqp::unbox_i(pos.Int))
  237. }
  238. multi method AT-POS(Any:U: Any:D \pos) is raw {
  239. self.AT-POS(nqp::unbox_i(pos.Int));
  240. }
  241. multi method AT-POS(Any:D: int \pos) is raw {
  242. pos
  243. ?? Failure.new(X::OutOfRange.new(
  244. :what($*INDEX // 'Index'), :got(pos), :range<0..0>))
  245. !! self
  246. }
  247. multi method AT-POS(Any:D: Int:D \pos) is raw {
  248. pos
  249. ?? Failure.new(X::OutOfRange.new(
  250. :what($*INDEX // 'Index'), :got(pos), :range<0..0>))
  251. !! self
  252. }
  253. multi method AT-POS(Any:D: Num:D \pos) is raw {
  254. nqp::isnanorinf(pos)
  255. ?? Failure.new(X::Item.new(aggregate => self, index => pos))
  256. !! self.AT-POS(nqp::unbox_i(pos.Int))
  257. }
  258. multi method AT-POS(Any:D: Any:D \pos) is raw {
  259. self.AT-POS(nqp::unbox_i(pos.Int));
  260. }
  261. multi method AT-POS(Any: Any:U \pos) is raw {
  262. die "Cannot use '{pos.^name}' as an index";
  263. }
  264. multi method AT-POS(Any:D: \one, \two) is raw {
  265. self.AT-POS(one).AT-POS(two)
  266. }
  267. multi method AT-POS(Any:D: \one, \two, \three) is raw {
  268. self.AT-POS(one).AT-POS(two).AT-POS(three)
  269. }
  270. multi method AT-POS(Any:D: **@indices) is raw {
  271. my $final := @indices.pop;
  272. Rakudo::Internals.WALK-AT-POS(self,@indices).AT-POS($final)
  273. }
  274. proto method ZEN-POS(|) { * }
  275. multi method ZEN-POS(*%unexpected) {
  276. %unexpected
  277. ?? Failure.new(X::Adverb.new(
  278. :what('[] slice'),
  279. :source(try { self.VAR.name } // self.WHAT.perl),
  280. :unexpected(%unexpected.keys)))
  281. !! self
  282. }
  283. proto method ZEN-KEY(|) { * }
  284. multi method ZEN-KEY(*%unexpected) {
  285. %unexpected
  286. ?? Failure.new(X::Adverb.new(
  287. :what('{} slice'),
  288. :source(try { self.VAR.name } // self.WHAT.perl),
  289. :unexpected(%unexpected.keys)))
  290. !! self
  291. }
  292. proto method ASSIGN-POS(|) is nodal { * }
  293. multi method ASSIGN-POS(Any:U \SELF: \pos, Mu \assignee) {
  294. SELF.AT-POS(pos) = assignee; # defer < 0 check
  295. }
  296. multi method ASSIGN-POS(Any:D: int \pos, Mu \assignee) {
  297. self.AT-POS(pos) = assignee; # defer < 0 check
  298. }
  299. multi method ASSIGN-POS(Any:D: Int:D \pos, Mu \assignee) {
  300. self.AT-POS(pos) = assignee; # defer < 0 check
  301. }
  302. multi method ASSIGN-POS(Any:D: Num:D \pos, Mu \assignee) {
  303. nqp::isnanorinf(pos)
  304. ?? Failure.new(X::Item.new(aggregate => self, index => pos))
  305. !! self.AT-POS(nqp::unbox_i(pos.Int)) = assignee; # defer < 0 check
  306. }
  307. multi method ASSIGN-POS(Any:D: Any:D \pos, Mu \assignee) {
  308. self.AT-POS(nqp::unbox_i(pos.Int)) = assignee; # defer < 0 check
  309. }
  310. multi method ASSIGN-POS(Any:D: Any:U \pos, Mu \assignee) {
  311. die "Cannot use '{pos.^name}' as an index";
  312. }
  313. multi method ASSIGN-POS(Any:D: \one, \two, Mu \assignee) is raw {
  314. self.AT-POS(one).ASSIGN-POS(two, assignee)
  315. }
  316. multi method ASSIGN-POS(Any:D: \one, \two, \three, Mu \assignee) is raw {
  317. self.AT-POS(one).AT-POS(two).ASSIGN-POS(three, assignee)
  318. }
  319. multi method ASSIGN-POS(Any:D: **@indices) {
  320. my \value := @indices.pop;
  321. my $final := @indices.pop;
  322. Rakudo::Internals.WALK-AT-POS(self,@indices).ASSIGN-POS($final,value)
  323. }
  324. proto method BIND-POS(|) { * }
  325. multi method BIND-POS(Any:D: **@indices is raw) is raw {
  326. # looks like Array.pop doesn't really return a bindable container
  327. # my \value := @indices.pop;
  328. # my $final := @indices.pop;
  329. # Rakudo::Internals.WALK-AT-POS(self,@indices).BIND-POS($final,value)
  330. my int $elems = @indices.elems; # reifies
  331. my \value := @indices.AT-POS(--$elems);
  332. my $final := @indices.AT-POS(--$elems);
  333. my $target := self;
  334. my int $i = -1;
  335. $target := $target.AT-POS(@indices.AT-POS($i))
  336. while nqp::islt_i(++$i,$elems);
  337. X::Bind.new.throw if $target =:= self;
  338. $target.BIND-POS($final, value)
  339. }
  340. method all() is nodal { Junction.new("all", self) }
  341. method any() is nodal { Junction.new("any", self) }
  342. method one() is nodal { Junction.new("one", self) }
  343. method none() is nodal { Junction.new("none",self) }
  344. # internals
  345. proto method AT-KEY(|) is nodal { * }
  346. multi method AT-KEY(Any:D: $key) is raw {
  347. Failure.new( self ~~ Associative
  348. ?? "Associative indexing implementation missing from type {self.WHAT.perl}"
  349. !! "Type {self.WHAT.perl} does not support associative indexing."
  350. )
  351. }
  352. multi method AT-KEY(Any:U \SELF: \key) is raw {
  353. nqp::p6bindattrinvres(
  354. my $scalar,
  355. Scalar,
  356. '$!whence',
  357. -> { nqp::if(
  358. nqp::isconcrete(SELF),
  359. SELF,
  360. (SELF = Hash.new)
  361. ).BIND-KEY(key, $scalar)
  362. }
  363. )
  364. }
  365. proto method BIND-KEY(|) is nodal { * }
  366. multi method BIND-KEY(Any:D: \k, \v) is raw {
  367. Failure.new(X::Bind.new(target => self.^name))
  368. }
  369. multi method BIND-KEY(Any:U \SELF: $key, $BIND ) is raw {
  370. SELF = Hash.new;
  371. SELF.BIND-KEY($key, $BIND);
  372. $BIND
  373. }
  374. proto method ASSIGN-KEY(|) is nodal { * }
  375. multi method ASSIGN-KEY(\SELF: \key, Mu \assignee) is raw {
  376. SELF.AT-KEY(key) = assignee;
  377. }
  378. # XXX GLR review these
  379. method FLATTENABLE_LIST() is nodal {
  380. my $list := self.list;
  381. nqp::findmethod($list, 'FLATTENABLE_LIST')($list);
  382. }
  383. method FLATTENABLE_HASH() is nodal { nqp::hash() }
  384. proto method Set(|) is nodal { * }
  385. multi method Set(Any:) { Set.new-from-pairs(self.list) }
  386. proto method SetHash(|) is nodal { * }
  387. multi method SetHash(Any:) { SetHash.new-from-pairs(self.list) }
  388. proto method Bag(|) is nodal { * }
  389. multi method Bag(Any:) { Bag.new-from-pairs(self.list) }
  390. proto method BagHash(|) is nodal { * }
  391. multi method BagHash(Any:) { BagHash.new-from-pairs(self.list) }
  392. proto method Mix(|) is nodal { * }
  393. multi method Mix(Any:) { Mix.new-from-pairs(self.list) }
  394. proto method MixHash(|) is nodal { * }
  395. multi method MixHash() { MixHash.new-from-pairs(self.list) }
  396. # XXX GLR does this really need to force a list?
  397. method Supply() is nodal { self.list.Supply }
  398. method nl-out() { "\n" }
  399. method print-nl() { self.print(self.nl-out) }
  400. method lazy-if($flag) { self } # no-op on non-Iterables
  401. method sum() is nodal {
  402. my \iter = self.iterator;
  403. my $sum = 0;
  404. my Mu $value;
  405. nqp::until(
  406. nqp::eqaddr(($value := iter.pull-one),IterationEnd),
  407. ($sum = $sum + $value)
  408. );
  409. $sum;
  410. }
  411. }
  412. Metamodel::ClassHOW.exclude_parent(Any);
  413. # builtin ops
  414. proto sub infix:<===>(Mu $?, Mu $?) is pure { * }
  415. multi sub infix:<===>($?) { Bool::True }
  416. multi sub infix:<===>(\a, \b) {
  417. nqp::p6bool(
  418. nqp::eqaddr(a,b)
  419. || (nqp::eqaddr(a.WHAT,b.WHAT)
  420. && nqp::iseq_s(nqp::unbox_s(a.WHICH), nqp::unbox_s(b.WHICH)))
  421. )
  422. }
  423. proto sub infix:<before>(Mu $?, Mu $?) is pure { * }
  424. multi sub infix:<before>($?) { Bool::True }
  425. multi sub infix:<before>(\a, \b) { (a cmp b) < 0 }
  426. proto sub infix:<after>(Mu $?, Mu $?) is pure { * }
  427. multi sub infix:<after>($x?) { Bool::True }
  428. multi sub infix:<after>(\a, \b) { (a cmp b) > 0 }
  429. proto prefix:<++>(Mu) { * }
  430. multi prefix:<++>(Mu:D $a is rw) { $a = $a.succ }
  431. multi prefix:<++>(Mu:U $a is rw) { $a = 1 }
  432. proto prefix:<-->(Mu) { * }
  433. multi prefix:<-->(Mu:D $a is rw) { $a = $a.pred }
  434. multi prefix:<-->(Mu:U $a is rw) { $a = -1 }
  435. proto postfix:<++>(Mu) { * }
  436. multi postfix:<++>(Mu:D $a is rw) { my $b = $a; $a = $a.succ; $b }
  437. multi postfix:<++>(Mu:U $a is rw) { $a = 1; 0 }
  438. proto postfix:<-->(Mu) { * }
  439. multi postfix:<-->(Mu:D $a is rw) { my $b = $a; $a = $a.pred; $b }
  440. multi postfix:<-->(Mu:U $a is rw) { $a = -1; 0 }
  441. proto sub pick(|) { * }
  442. multi sub pick($n, +values) { values.pick($n) }
  443. proto sub roll(|) { * }
  444. multi sub roll($n, +values) { values.roll($n) }
  445. proto sub keys(|) { * }
  446. multi sub keys($x) { $x.keys }
  447. proto sub values(|) { * }
  448. multi sub values($x) { $x.values }
  449. proto sub pairs(|) { * }
  450. multi sub pairs($x) { $x.pairs }
  451. proto sub kv(|) { * }
  452. multi sub kv($x) { $x.kv }
  453. proto sub elems(|) is nodal { * }
  454. multi sub elems($a) { $a.elems }
  455. proto sub end(|) { * }
  456. multi sub end($a) { $a.end }
  457. proto sub sum(|) {*}
  458. multi sub sum() { 0 }
  459. multi sub sum(\SELF) { SELF.sum }
  460. multi sub sum(+SELF) { SELF.sum }
  461. sub classify( $test, +items, *%named ) {
  462. if %named.EXISTS-KEY("into") {
  463. my $into := %named.DELETE-KEY("into");
  464. ( $into // $into.new).classify-list($test, items, |%named);
  465. }
  466. else {
  467. Hash.^parameterize(Any,Any).new.classify-list($test, items, |%named);
  468. }
  469. }
  470. sub categorize( $test, +items, *%named ) {
  471. if %named.EXISTS-KEY("into") {
  472. my $into := %named.DELETE-KEY("into");
  473. ( $into // $into.new).categorize-list($test, items, |%named);
  474. }
  475. else {
  476. Hash.^parameterize(Any,Any).new.categorize-list($test, items, |%named);
  477. }
  478. }
  479. proto sub item(|) is pure { * }
  480. multi sub item(\x) { my $ = x }
  481. multi sub item(|c) { my $ = c.list }
  482. multi sub item(Mu $a) { $a }
  483. sub SLICE_HUH(\SELF, @nogo, %d, %adv) {
  484. @nogo.unshift('delete') # recover any :delete if necessary
  485. if @nogo && @nogo[0] ne 'delete' && %adv.EXISTS-KEY('delete');
  486. for <delete exists kv p k v> -> $valid { # check all valid params
  487. if nqp::existskey(%d,nqp::unbox_s($valid)) {
  488. nqp::deletekey(%d,nqp::unbox_s($valid));
  489. @nogo.push($valid);
  490. }
  491. }
  492. Failure.new(X::Adverb.new(
  493. :what<slice>,
  494. :source(try { SELF.VAR.name } // SELF.WHAT.perl),
  495. :unexpected(%d.keys),
  496. :nogo(@nogo),
  497. ))
  498. } #SLICE_HUH
  499. sub DELETEKEY(Mu \d, str $key) {
  500. nqp::if(
  501. nqp::existskey(d,$key),
  502. nqp::stmts(
  503. (my Mu $value := nqp::atkey(d,$key)),
  504. (nqp::deletekey(d,$key)),
  505. $value
  506. ),
  507. Nil
  508. )
  509. } #DELETEKEY
  510. sub dd(|) {
  511. my Mu $args := nqp::p6argvmarray();
  512. if nqp::elems($args) {
  513. while $args {
  514. my $var := nqp::shift($args);
  515. my $name := try $var.VAR.?name;
  516. my $type := $var.WHAT.^name;
  517. my $what := $var.?is-lazy
  518. ?? $var[^10].perl.chop ~ "... lazy list)"
  519. !! $var.perl;
  520. note $name ?? "$type $name = $what" !! $what;
  521. }
  522. }
  523. else { # tell where we are
  524. note .name ?? "{lc .^name} {.name}" !! "({lc .^name})"
  525. with callframe(1).code;
  526. }
  527. return
  528. }