1. BEGIN {
  2. # Workaround for regression in https://github.com/rakudo/rakudo/issues/1566
  3. # The actual bug is that Callable role gets mixed in into routines
  4. # before it's composed, and when it is composed, the routines end up
  5. # not "doing" `Callable` role, even though they do. There are many more
  6. # routines suffering this issue, but these three regressed since last
  7. # release and we don't have the time to fix the primary bug before the
  8. # release, so in this fudge goes.
  9. &min.^compose;
  10. &max.^compose;
  11. &minmax.^compose;
  12. }
  13. my class Cool { # declared in BOOTSTRAP
  14. # class Cool is Any
  15. ## numeric methods
  16. method abs() { self.Numeric.abs }
  17. method conj() { self.Numeric.conj }
  18. method sqrt() { self.Numeric.sqrt }
  19. method sign() { self.Real.sign }
  20. method rand() { self.Num.rand }
  21. method sin() { self.Numeric.sin }
  22. method asin() { self.Numeric.asin }
  23. method cos() { self.Numeric.cos }
  24. method acos() { self.Numeric.acos }
  25. method tan() { self.Numeric.tan }
  26. method atan() { self.Numeric.atan }
  27. method atan2($y = 1e0) { self.Numeric.atan2($y.Numeric) }
  28. method sec() { self.Numeric.sec }
  29. method asec() { self.Numeric.asec }
  30. method cosec() { self.Numeric.cosec }
  31. method acosec() { self.Numeric.acosec }
  32. method cotan() { self.Numeric.cotan }
  33. method acotan() { self.Numeric.acotan }
  34. method sinh() { self.Numeric.sinh }
  35. method asinh() { self.Numeric.asinh }
  36. method cosh() { self.Numeric.cosh }
  37. method acosh() { self.Numeric.acosh }
  38. method tanh() { self.Numeric.tanh }
  39. method atanh() { self.Numeric.atanh }
  40. method sech() { self.Numeric.sech }
  41. method asech() { self.Numeric.asech }
  42. method cosech() { self.Numeric.cosech }
  43. method acosech() { self.Numeric.acosech }
  44. method cotanh() { self.Numeric.cotanh }
  45. method acotanh() { self.Numeric.acotanh }
  46. method cis() { self.Numeric.cis }
  47. method is-prime(--> Bool:D) { self.Real.is-prime }
  48. proto method log(|) {*}
  49. multi method log(Cool:D: ) { self.Numeric.log }
  50. multi method log(Cool:D: $base) { self.Numeric.log($base.Numeric) }
  51. proto method exp(|) {*}
  52. multi method exp(Cool:D: ) { self.Numeric.exp }
  53. multi method exp(Cool:D: $base) { self.Numeric.exp($base.Numeric) }
  54. proto method round(|) {*}
  55. multi method round() { self.Numeric.round() }
  56. multi method round($base) { self.Numeric.round($base) }
  57. method roots(Cool $n) { self.Numeric.roots($n) }
  58. method log10() { self.Numeric.log10 }
  59. method unpolar($n) { self.Numeric.unpolar($n.Numeric) }
  60. method floor() { self.Numeric.floor }
  61. method ceiling() { self.Numeric.ceiling }
  62. method truncate() { self.Numeric.truncate }
  63. ## string methods
  64. method chars(--> Int:D) {
  65. self.Str.chars
  66. }
  67. method codes() {
  68. self.Str.codes
  69. }
  70. method fmt($format = '%s') {
  71. Rakudo::Internals.initialize-sprintf-handler;
  72. nqp::p6box_s(
  73. nqp::sprintf(nqp::unbox_s($format.Stringy), nqp::list(self))
  74. )
  75. }
  76. method uc() {
  77. self.Str.uc
  78. }
  79. method lc() {
  80. self.Str.lc
  81. }
  82. method tc() {
  83. self.Str.tc
  84. }
  85. method fc() {
  86. self.Str.fc
  87. }
  88. method tclc() {
  89. self.Str.tclc
  90. }
  91. method wordcase() { self.Str.wordcase }
  92. method uniname() { uniname(self) }
  93. method uninames() { uninames(self) }
  94. method unival() { unival(self) }
  95. method univals() { univals(self) }
  96. method uniprop(|c) { uniprop(self, |c) }
  97. method uniprop-int(|c) { uniprop-int(self, |c) }
  98. method uniprop-bool(|c) { uniprop-bool(self, |c) }
  99. method uniprop-str(|c) { uniprop-str(self, |c) }
  100. method uniprops(|c) { uniprops(self, |c) }
  101. method unimatch(|c) { unimatch(self, |c) }
  102. method chomp(Cool:D:) { self.Str.chomp }
  103. proto method chop(|) {*}
  104. multi method chop(Cool:D:) { self.Str.chop }
  105. multi method chop(Cool:D: Int() $n) { self.Str.chop($n) }
  106. method ord(--> Int:D) {
  107. self.Str.ord
  108. }
  109. method chr() {
  110. self.Int.chr;
  111. }
  112. proto method chrs(|) {*}
  113. multi method chrs(Cool:D:) { self.list.chrs }
  114. proto method ords(|) {*}
  115. multi method ords(Cool:D:) { self.Str.ords }
  116. method flip() {
  117. self.Str.flip
  118. }
  119. method trans(|c) { self.Str.trans(|c) }
  120. method starts-with(Cool:D: |c) {
  121. self.Str.starts-with(|c)
  122. }
  123. method ends-with(Cool:D: |c) {
  124. self.Str.ends-with(|c)
  125. }
  126. proto method substr(|) {*}
  127. multi method substr() { self.Str.substr }
  128. multi method substr(\from) { self.Str.substr(from) }
  129. multi method substr(\from, \chars) { self.Str.substr(from,chars) }
  130. proto method substr-rw(|) {*}
  131. multi method substr-rw(\SELF:) is rw {
  132. (SELF = self.Str).substr-rw
  133. }
  134. multi method substr-rw(\SELF: \from) is rw {
  135. (SELF = self.Str).substr-rw(from)
  136. }
  137. multi method substr-rw(\SELF: \from, \chars) is rw {
  138. (SELF = self.Str).substr-rw(from,chars)
  139. }
  140. method substr-eq(Cool:D: |c) {
  141. self.Str.substr-eq(|c)
  142. }
  143. method contains(Cool:D: |c) {
  144. self.Str.contains(|c)
  145. }
  146. method indices(Cool:D: |c) {
  147. self.Str.indices(|c)
  148. }
  149. method index(Cool:D: |c) {
  150. self.Str.index(|c)
  151. }
  152. method rindex(Cool:D: |c) {
  153. self.Str.rindex(|c)
  154. }
  155. method split(Cool: |c) {
  156. self.Stringy.split(|c);
  157. }
  158. method match(Cool:D: |c) {
  159. $/ := nqp::getlexcaller('$/');
  160. self.Stringy.match(|c)
  161. }
  162. method comb(|c) { self.Str.comb(|c) }
  163. method lines(Cool:D: |c) { self.Str.lines(|c) }
  164. method words(Cool:D: |c) { self.Str.words(|c) }
  165. method subst(|c) {
  166. $/ := nqp::getlexcaller('$/');
  167. self.Stringy.subst(|c);
  168. }
  169. # `$value-to-subst-mutate` will show up in errors when called on non-rw
  170. # container, so use more descriptive name instead of just `$self`
  171. method subst-mutate(Cool:D $value-to-subst-mutate is rw: |c) {
  172. $/ := nqp::getlexcaller('$/');
  173. my $str = $value-to-subst-mutate.Str;
  174. my $match := $str.subst-mutate(|c);
  175. $value-to-subst-mutate = $str if $match; # only change if successful
  176. $match
  177. }
  178. proto method IO(|) {*}
  179. multi method IO(Cool:D:) { IO::Path.new(self) }
  180. multi method IO(Cool:U:) { IO::Path }
  181. method sprintf(*@args) { sprintf(self, @args) };
  182. method printf (*@args) { printf(self, @args) };
  183. method samecase(Cool:D: Cool $pattern) { self.Stringy.samecase($pattern) }
  184. method path() { self.Stringy.IO }
  185. method trim () { self.Stringy.trim };
  186. method trim-leading () { self.Stringy.trim-leading };
  187. method trim-trailing() { self.Stringy.trim-trailing };
  188. method EVAL(*%opts) {
  189. EVAL(self, context => CALLER::, |%opts);
  190. }
  191. multi method Real() {
  192. nqp::if(
  193. nqp::istype((my $numeric := self.Numeric), Failure),
  194. $numeric,
  195. $numeric.Real
  196. )
  197. }
  198. proto method Int(|) {*}
  199. multi method Int() {
  200. nqp::if(
  201. nqp::istype((my $numeric := self.Numeric), Failure),
  202. $numeric,
  203. $numeric.Int
  204. )
  205. }
  206. proto method UInt(|) {*}
  207. multi method UInt() {
  208. my $got := self.Int;
  209. $got < 0
  210. ?? Failure.new(X::OutOfRange.new(
  211. :what('Coercion to UInt'),
  212. :$got,
  213. :range<0..^Inf>))
  214. !! $got
  215. }
  216. method Num() {
  217. nqp::if(
  218. nqp::istype((my $numeric := self.Numeric), Failure),
  219. $numeric,
  220. $numeric.Num
  221. )
  222. }
  223. method Rat() {
  224. nqp::if(
  225. nqp::istype((my $numeric := self.Numeric), Failure),
  226. $numeric,
  227. $numeric.Rat
  228. )
  229. }
  230. method FatRat() {
  231. nqp::if(
  232. nqp::istype((my $numeric := self.Numeric), Failure),
  233. $numeric,
  234. $numeric.FatRat
  235. )
  236. }
  237. method Complex() {
  238. nqp::if(
  239. nqp::istype((my $numeric := self.Numeric), Failure),
  240. $numeric,
  241. $numeric.Complex
  242. )
  243. }
  244. }
  245. Metamodel::ClassHOW.exclude_parent(Cool);
  246. proto sub chop(|) {*}
  247. multi sub chop(Cool:D $s --> Str:D) { $s.chop }
  248. multi sub chop(Cool:D $s, Int() $n --> Str:D) { $s.chop($n) }
  249. proto sub chomp(|) {*}
  250. multi sub chomp(Cool $s --> Str:D) { $s.chomp }
  251. proto sub flip(|) {*}
  252. multi sub flip(Cool $s --> Str:D) { $s.flip }
  253. proto sub index(|) {*}
  254. multi sub index(Cool $s, Cool $needle) { $s.index($needle) }
  255. multi sub index(Cool $s, Cool $needle, Cool $pos) { $s.index($needle,$pos) }
  256. proto sub rindex(|) {*}
  257. multi sub rindex(Cool $s, Cool $needle, Cool $pos) { $s.rindex($needle, $pos) }
  258. multi sub rindex(Cool $s, Cool $needle) { $s.rindex($needle) }
  259. proto sub lc(|) {*}
  260. multi sub lc(Cool $s) { $s.lc }
  261. proto sub ord(|) {*}
  262. multi sub ord(Cool $s) { $s.ord }
  263. proto sub uc(|) {*}
  264. multi sub uc(Cool $s) { $s.uc }
  265. proto sub tc(|) {*}
  266. multi sub tc(Cool $s) { $s.tc }
  267. proto sub fc(|) {*}
  268. multi sub fc(Cool $s) { $s.fc }
  269. proto sub tclc(|) {*}
  270. multi sub tclc(Cool $s) { $s.tclc }
  271. proto sub indices(|) {*}
  272. multi sub indices(Cool $s, |c) { $s.indices(|c) }
  273. proto sub ords($) {*}
  274. multi sub ords(Cool:D $s) { $s.ords }
  275. proto sub comb($, $, $?) {*}
  276. multi sub comb(Regex $matcher, Cool $input, $limit = *) { $input.comb($matcher, $limit) }
  277. multi sub comb(Str $matcher, Cool $input, $limit = *) { $input.comb($matcher, $limit) }
  278. multi sub comb(Int:D $matcher, Cool $input, $limit = *) { $input.comb($matcher, $limit) }
  279. proto sub wordcase($) is pure {*}
  280. multi sub wordcase(Str:D $x) {$x.wordcase }
  281. multi sub wordcase(Cool $x) {$x.Str.wordcase }
  282. proto sub sprintf(|) {*}
  283. multi sub sprintf(Cool:D $format, *@args) {
  284. CATCH {
  285. when X::Cannot::Lazy {
  286. X::Cannot::Lazy.new(:action('(s)printf')).throw
  287. }
  288. default {
  289. Rakudo::Internals.HANDLE-NQP-SPRINTF-ERRORS($_).throw
  290. }
  291. }
  292. Rakudo::Internals.initialize-sprintf-handler;
  293. @args.elems;
  294. nqp::p6box_s(
  295. nqp::sprintf(nqp::unbox_s($format.Stringy),
  296. nqp::clone(nqp::getattr(@args||[], List, '$!reified'))
  297. )
  298. )
  299. }
  300. proto sub printf(|) {*}
  301. multi sub printf(Cool:D $format, *@args) { print sprintf $format, @args }
  302. proto sub samecase(|) {*}
  303. multi sub samecase(Cool:D $string, Cool:D $pattern) { $string.samecase($pattern) }
  304. proto sub split(|) {*}
  305. multi sub split($pat, Cool:D $target, |c) { $target.split($pat, |c) }
  306. proto sub chars($) is pure {*}
  307. multi sub chars(Cool $x) { $x.Str.chars }
  308. multi sub chars(Str:D $x) { nqp::p6box_i(nqp::chars($x)) }
  309. multi sub chars(str $x --> int) { nqp::chars($x) }
  310. # These probably belong in a separate unicodey file
  311. proto sub uniname(|) {*}
  312. multi sub uniname(Str:D $str) { $str ?? uniname($str.ord) !! Nil }
  313. multi sub uniname(Int:D $code) { nqp::getuniname($code) }
  314. proto sub uninames(|) {*}
  315. multi sub uninames(Str:D $str) { $str.NFC.map: { uniname($_) } }
  316. proto sub uniprop(|) {*}
  317. multi sub uniprop(Str:D $str, |c) { $str ?? uniprop($str.ord, |c) !! Nil }
  318. multi sub uniprop(Int:D $code) {
  319. nqp::getuniprop_str($code,nqp::unipropcode('General_Category'));
  320. }
  321. multi sub uniprop(Int:D $code, Stringy:D $propname) {
  322. # prop-mappings can be removed when MoarVM bug #448 is fixed...
  323. ## The code below was generated by tools/build/makeUNIPROP.pl6
  324. my constant $prop-mappings = nqp::hash(
  325. 'OGr_Ext','Other_Grapheme_Extend','tc','Titlecase_Mapping',
  326. 'cjkIRG_MSource','kIRG_MSource','Dash','Dash','Pat_Syn','Pattern_Syntax',
  327. 'IDST','IDS_Trinary_Operator','IDC','ID_Continue','Dia','Diacritic',
  328. 'Cased','Cased','hst','Hangul_Syllable_Type','QMark','Quotation_Mark',
  329. 'Radical','Radical','NFD_QC','NFD_Quick_Check','jt','Joining_Type',
  330. 'cf','Case_Folding','cjkIRG_TSource','kIRG_TSource','sc','Script',
  331. 'SD','Soft_Dotted','CWCM','Changes_When_Casemapped',
  332. 'cjkOtherNumeric','kOtherNumeric','scf','Simple_Case_Folding',
  333. 'sfc','Simple_Case_Folding','isc','ISO_Comment','na1','Unicode_1_Name',
  334. 'Lower','Lowercase','Join_C','Join_Control','JSN','Jamo_Short_Name',
  335. 'bc','Bidi_Class','jg','Joining_Group','dm','Decomposition_Mapping',
  336. 'lc','Lowercase_Mapping','cjkIRG_USource','kIRG_USource',
  337. 'NFKC_CF','NFKC_Casefold','slc','Simple_Lowercase_Mapping',
  338. 'InSC','Indic_Syllabic_Category','XO_NFC','Expands_On_NFC',
  339. 'XO_NFD','Expands_On_NFD','cjkAccountingNumeric','kAccountingNumeric',
  340. 'Upper','Uppercase','WSpace','White_Space','space','White_Space',
  341. 'cjkIRG_VSource','kIRG_VSource','STerm','Sentence_Terminal',
  342. 'NFKD_QC','NFKD_Quick_Check','CWT','Changes_When_Titlecased','Math','Math',
  343. 'uc','Uppercase_Mapping','NFKC_QC','NFKC_Quick_Check','SB','Sentence_Break',
  344. 'stc','Simple_Titlecase_Mapping','Alpha','Alphabetic',
  345. 'CE','Composition_Exclusion','NChar','Noncharacter_Code_Point',
  346. 'OAlpha','Other_Alphabetic','XIDC','XID_Continue','age','Age',
  347. 'cjkPrimaryNumeric','kPrimaryNumeric','OIDS','Other_ID_Start',
  348. 'UIdeo','Unified_Ideograph','FC_NFKC','FC_NFKC_Closure','CI','Case_Ignorable',
  349. 'Hyphen','Hyphen','nv','Numeric_Value','CWKCF','Changes_When_NFKC_Casefolded',
  350. 'XO_NFKD','Expands_On_NFKD','InPC','Indic_Positional_Category',
  351. 'dt','Decomposition_Type','cjkIICore','kIICore','Bidi_M','Bidi_Mirrored',
  352. 'CWU','Changes_When_Uppercased','IDS','ID_Start','Gr_Ext','Grapheme_Extend',
  353. 'XIDS','XID_Start','XO_NFKC','Expands_On_NFKC','OUpper','Other_Uppercase',
  354. 'OMath','Other_Math','Gr_Link','Grapheme_Link','Bidi_C','Bidi_Control',
  355. 'DI','Default_Ignorable_Code_Point','CWCF','Changes_When_Casefolded',
  356. 'cjkIRG_GSource','kIRG_GSource','WB','Word_Break','NFC_QC','NFC_Quick_Check',
  357. 'cjkIRG_JSource','kIRG_JSource','ODI','Other_Default_Ignorable_Code_Point',
  358. 'LOE','Logical_Order_Exception','bpb','Bidi_Paired_Bracket',
  359. 'PCM','Prepended_Concatenation_Mark','OLower','Other_Lowercase',
  360. 'OIDC','Other_ID_Continue','VS','Variation_Selector','Ext','Extender',
  361. 'Comp_Ex','Full_Composition_Exclusion','IDSB','IDS_Binary_Operator',
  362. 'nt','Numeric_Type','cjkCompatibilityVariant','kCompatibilityVariant',
  363. 'suc','Simple_Uppercase_Mapping','Term','Terminal_Punctuation',
  364. 'lb','Line_Break','cjkIRG_HSource','kIRG_HSource','ea','East_Asian_Width',
  365. 'AHex','ASCII_Hex_Digit','cjkIRG_KSource','kIRG_KSource',
  366. 'Pat_WS','Pattern_White_Space','Hex','Hex_Digit',
  367. 'cjkIRG_KPSource','kIRG_KPSource','bpt','Bidi_Paired_Bracket_Type',
  368. 'gc','General_Category','GCB','Grapheme_Cluster_Break',
  369. 'Gr_Base','Grapheme_Base','na','Name','scx','Script_Extensions',
  370. 'Ideo','Ideographic','Name_Alias','Name_Alias','blk','Block','Dep','Deprecated',
  371. 'CWL','Changes_When_Lowercased','bmg','Bidi_Mirroring_Glyph',
  372. 'cjkRSUnicode','kRSUnicode','Unicode_Radical_Stroke','kRSUnicode',
  373. 'URS','kRSUnicode','ccc','Canonical_Combining_Class',
  374. );
  375. my constant $prefs = nqp::hash(
  376. 'Other_Grapheme_Extend','B','Titlecase_Mapping','tc','Dash','B',
  377. 'Emoji_Modifier_Base','B','Emoji_Modifier','B','Pattern_Syntax','B',
  378. 'IDS_Trinary_Operator','B','ID_Continue','B','Diacritic','B','Cased','B',
  379. 'Hangul_Syllable_Type','S','Quotation_Mark','B','Radical','B',
  380. 'NFD_Quick_Check','S','Joining_Type','S','Case_Folding','S','Script','S',
  381. 'Soft_Dotted','B','Changes_When_Casemapped','B','Simple_Case_Folding','S',
  382. 'ISO_Comment','S','Lowercase','B','Join_Control','B','Bidi_Class','S',
  383. 'Joining_Group','S','Decomposition_Mapping','S','Lowercase_Mapping','lc',
  384. 'NFKC_Casefold','S','Simple_Lowercase_Mapping','S',
  385. 'Indic_Syllabic_Category','S','Expands_On_NFC','B','Expands_On_NFD','B',
  386. 'Uppercase','B','White_Space','B','Sentence_Terminal','B',
  387. 'NFKD_Quick_Check','S','Changes_When_Titlecased','B','Math','B',
  388. 'Uppercase_Mapping','uc','NFKC_Quick_Check','S','Sentence_Break','S',
  389. 'Simple_Titlecase_Mapping','S','Alphabetic','B','Composition_Exclusion','B',
  390. 'Noncharacter_Code_Point','B','Other_Alphabetic','B','XID_Continue','B',
  391. 'Age','S','Other_ID_Start','B','Unified_Ideograph','B','FC_NFKC_Closure','S',
  392. 'Case_Ignorable','B','Hyphen','B','Numeric_Value','nv',
  393. 'Changes_When_NFKC_Casefolded','B','Expands_On_NFKD','B',
  394. 'Indic_Positional_Category','S','Decomposition_Type','S','Bidi_Mirrored','B',
  395. 'Changes_When_Uppercased','B','ID_Start','B','Grapheme_Extend','B',
  396. 'XID_Start','B','Expands_On_NFKC','B','Other_Uppercase','B','Other_Math','B',
  397. 'Grapheme_Link','B','Bidi_Control','B','Default_Ignorable_Code_Point','B',
  398. 'Changes_When_Casefolded','B','Word_Break','S','NFC_Quick_Check','S',
  399. 'Other_Default_Ignorable_Code_Point','B','Logical_Order_Exception','B',
  400. 'Prepended_Concatenation_Mark','B','Other_Lowercase','B',
  401. 'Other_ID_Continue','B','Variation_Selector','B','Extender','B',
  402. 'Full_Composition_Exclusion','B','IDS_Binary_Operator','B','Numeric_Type','S',
  403. 'kCompatibilityVariant','S','Simple_Uppercase_Mapping','S',
  404. 'Terminal_Punctuation','B','Line_Break','S','East_Asian_Width','S',
  405. 'ASCII_Hex_Digit','B','Pattern_White_Space','B','Hex_Digit','B',
  406. 'Bidi_Paired_Bracket_Type','S','General_Category','S',
  407. 'Grapheme_Cluster_Break','S','Grapheme_Base','B','Name','na','Ideographic','B',
  408. 'Block','S','Emoji_Presentation','B','Emoji','B','Deprecated','B',
  409. 'Changes_When_Lowercased','B','Bidi_Mirroring_Glyph','bmg',
  410. 'Canonical_Combining_Class','S',
  411. );
  412. ## End generated code
  413. $propname := nqp::atkey($prop-mappings, $propname) if nqp::existskey($prop-mappings,$propname);
  414. my $prop := nqp::unipropcode($propname);
  415. my str $pref = nqp::ifnull(nqp::atkey($prefs, $propname),'');
  416. nqp::if(
  417. nqp::iseq_s($pref, 'S'),
  418. nqp::getuniprop_str($code,$prop),
  419. nqp::if(
  420. nqp::iseq_s($pref, 'I'),
  421. nqp::getuniprop_int($code,$prop),
  422. nqp::if(
  423. nqp::iseq_s($pref, 'B'),
  424. nqp::p6bool(nqp::getuniprop_bool($code,$prop)),
  425. nqp::if(
  426. nqp::iseq_s($pref, 'lc'),
  427. nqp::lc(nqp::chr(nqp::unbox_i($code))),
  428. nqp::if(
  429. nqp::iseq_s($pref, 'tc'),
  430. nqp::tc(nqp::chr(nqp::unbox_i($code))),
  431. nqp::if(
  432. nqp::iseq_s($pref, 'uc'),
  433. nqp::uc(nqp::chr(nqp::unbox_i($code))),
  434. nqp::if(
  435. nqp::iseq_s($pref, 'na'),
  436. nqp::getuniname($code),
  437. nqp::if(
  438. nqp::iseq_s($pref, 'nv'),
  439. unival($code),
  440. nqp::if(
  441. nqp::iseq_s($pref, 'bmg'),
  442. nqp::stmts(
  443. (my int $bmg-ord = nqp::getuniprop_int($code, $prop)),
  444. $bmg-ord ?? nqp::chr($bmg-ord) !! ''),
  445. nqp::stmts(
  446. (my $result := nqp::getuniprop_str($code,$prop)),
  447. nqp::if(
  448. nqp::istrue($result),
  449. nqp::stmts(
  450. nqp::bindkey($prefs, $propname, 'S'),
  451. $result),
  452. nqp::stmts(
  453. nqp::bindkey($prefs, $propname, 'I'),
  454. nqp::getuniprop_int($code,$prop)))))))))))))
  455. }
  456. # Unicode functions
  457. proto sub uniprop-int(|) {*}
  458. multi sub uniprop-int(Str:D $str, Stringy:D $propname) {
  459. $str ?? uniprop-int($str.ord, $propname) !! Nil }
  460. multi sub uniprop-int(Int:D $code, Stringy:D $propname) {
  461. nqp::getuniprop_int($code,nqp::unipropcode($propname));
  462. }
  463. proto sub uniprop-bool(|) {*}
  464. multi sub uniprop-bool(Str:D $str, Stringy:D $propname) {
  465. $str ?? uniprop-bool($str.ord, $propname) !! Nil
  466. }
  467. multi sub uniprop-bool(Int:D $code, Stringy:D $propname) {
  468. nqp::p6bool(nqp::getuniprop_bool($code,nqp::unipropcode($propname)));
  469. }
  470. proto sub uniprop-str(|) {*}
  471. multi sub uniprop-str(Str:D $str, Stringy:D $propname) {
  472. $str ?? uniprop-str($str.ord, $propname) !! Nil
  473. }
  474. multi sub uniprop-str(Int:D $code, Stringy:D $propname) {
  475. nqp::getuniprop_str($code,nqp::unipropcode($propname));
  476. }
  477. proto sub uniprops(|) {*}
  478. multi sub uniprops(Str:D $str, Stringy:D $propname = "General_Category") {
  479. $str.ords.map: { uniprop($_, $propname) }
  480. }
  481. proto sub unival(|) {*}
  482. multi sub unival(Str:D $str) { $str ?? unival($str.ord) !! Nil }
  483. multi sub unival(Int:D $code) {
  484. state $nuprop = nqp::unipropcode("Numeric_Value_Numerator");
  485. state $deprop = nqp::unipropcode("Numeric_Value_Denominator");
  486. my $nu = nqp::getuniprop_str($code, $nuprop);
  487. my $de = nqp::getuniprop_str($code, $deprop);
  488. !$de || $de eq '1' ?? $nu.Int !! $nu / $de;
  489. }
  490. proto sub univals(|) {*}
  491. multi sub univals(Str:D $str) { $str.ords.map: { unival($_) } }
  492. proto sub unimatch(|) {*}
  493. multi sub unimatch(Str:D $str, |c) { $str ?? unimatch($str.ord, |c) !! Nil }
  494. # This multi below can be removed when MoarVM bug #448 is fixed
  495. multi sub unimatch(Int:D $code, Stringy:D $pvalname, Stringy:D $propname) {
  496. uniprop($code, $propname) eq $pvalname;
  497. }
  498. multi sub unimatch(Int:D $code, Stringy:D $pvalname, Stringy:D $propname = $pvalname) {
  499. my $prop := nqp::unipropcode($propname);
  500. nqp::p6bool(nqp::matchuniprop($code,$prop,nqp::unipvalcode($prop,$pvalname)));
  501. }