3
Str - Perl 6 Str class and related functions
7
This file sets up the C<Perl6Str> PMC type (from F<src/pmc/perl6str.pmc>)
8
as the Perl 6 C<Str> class.
18
.include 'cclass.pasm'
20
.sub 'onload' :anon :init :load
21
.local pmc p6meta, strproto
22
p6meta = get_hll_global ['Perl6Object'], '$!P6META'
23
strproto = p6meta.'new_class'('Str', 'parent'=>'parrot;Perl6Str Any')
24
strproto.'!IMMUTABLE'()
25
p6meta.'register'('Perl6Str', 'parent'=>strproto, 'protoobject'=>strproto)
26
p6meta.'register'('String', 'parent'=>strproto, 'protoobject'=>strproto)
28
$P0 = get_hll_namespace ['Str']
29
'!EXPORT'('sprintf', 'from'=>$P0)
33
.sub 'ACCEPTS' :method
35
.tailcall 'infix:eq'(topic, self)
41
Returns a Perl representation of the Str.
46
.local string str, result
52
arr = root_new ['parrot';'ResizablePMCArray']
55
ch = substr str, pos, 1
57
if ch == ' ' goto loop_ch
58
## check for special escapes
59
$I0 = index "$ @ % & { \b \n \r \t \\ \"", ch
60
if $I0 < 0 goto loop_nonprint
61
ch = substr "\\$\\@\\%\\&\\{\\b\\n\\r\\t\\\\\\\"", $I0, 2
64
$I0 = is_cclass .CCLASS_PRINTING, ch, 0
68
ch = sprintf '\x[%x]', arr
79
=item sprintf( *@args )
83
.sub 'sprintf' :method
84
.param pmc args :slurpy
88
sprintf $P0, self, args
93
.tailcall '!FAIL'('Insufficient arguments supplied to sprintf')
98
Increment and Decrement Methods
104
## The RANGES constant indicates the successor to each character in
105
## a defined range. ## Currently supported increment/decrement ranges:
106
## 0..9 ASCII digits (U+0030..U+0039)
107
## A..Z ASCII uc (U+0041..U+005a)
108
## a..z ASCII lc (U+0061..U+006a)
109
## Α..Ω Greek uc (U+0391..U+03a9, skip u+03a2)
110
## α..ω Greek lc (U+03b1..U+03c9, skip u+03c2)
111
## Ⅰ..Ⅻ clock roman uc (U+2160..U+216b)
112
## ⅰ..ⅻ clock roman lc (U+2170..U+217b)
113
## ①..⑳ circled digits (U+2460..U+2473)
114
## ⑴..⒇ parenth digits (U+2474..U+2487)
115
## ⒜..⒵ parenth lc (U+249c..U+24b5)
116
## ⚀..⚅ die faces (U+2680..U+2685)
117
## Note that in each cycle, the first character of the cycle is repeated
118
## at the end of the cycle (to indicate carries).
120
.const string RANGES = unicode:"01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZAabcdefghijklmnopqrstuvwxyza\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u0391\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03b1\u2160\u2161\u2162\u2163\u2164\u2165\u2166\u2167\u2168\u2169\u216a\u216b\u2160\u2170\u2171\u2172\u2173\u2174\u2175\u2176\u2177\u2178\u2179\u217a\u217b\u2170\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468\u2469\u246a\u246b\u246c\u246d\u246e\u246f\u2470\u2471\u2472\u2473\u2460\u2474\u2475\u2476\u2477\u2478\u2479\u247a\u247b\u247c\u247d\u247e\u247f\u2480\u2481\u2482\u2483\u2484\u2485\u2486\u2487\u2474\u249c\u249d\u249e\u249f\u24a0\u24a1\u24a2\u24a3\u24a4\u24a5\u24a6\u24a7\u24a8\u24a9\u24aa\u24ab\u24ac\u24ad\u24ae\u24af\u24b0\u24b1\u24b2\u24b3\u24b4\u24b5\u249c\u2680\u2681\u2682\u2683\u2684\u2685\u2680"
122
.sub '!range_pos' :anon
125
.local int len, pos, r0, r1
128
# Scan from the end of a string for a character that is in RANGES.
129
# This is the potential end of the substring to be incremented.
132
# Reset range positions to indicate that we haven't found a valid substr
136
unless pos > 0 goto done
138
$S0 = substr str, pos, 1
139
$I0 = index RANGES, $S0
140
if $I0 < 0 goto scan_end_loop
142
# we found a candidate end of the range, now scan for start
145
# if we reach the beginning of the string, the range starts at pos 0
146
unless pos > 0 goto done
148
$S0 = substr str, pos, 1
149
# if we find a dot: this isn't a valid range, scan again
150
if $S0 == '.' goto scan_loop
151
# if we find a valid character, keep scanning
152
$I0 = index RANGES, $S0
153
if $I0 >= 0 goto scan_start_loop
154
# pos + 1 is the start of the range, we're done
167
.local int r0, r1, ipos
168
(r0, r1) = '!range_pos'(str)
172
.local string orig, repl
173
orig = substr str, r1, 1
174
ipos = index RANGES, orig
176
$I0 = index RANGES, orig, $I0
177
if $I0 < 0 goto dec_2
181
repl = substr RANGES, ipos, 1
182
substr str, r1, 1, repl
183
# if the replacement wasn't a carry, we're done
184
if orig > repl goto done
186
# if there are more characters in the range, decrement those first
188
if r1 >= r0 goto dec_1
190
.tailcall '!FAIL'('Decrement out of range')
202
.local int r0, r1, ipos
203
(r0, r1) = '!range_pos'(str)
207
.local string orig, repl
208
orig = substr str, r1, 1
209
ipos = index RANGES, orig
212
repl = substr RANGES, ipos, 1
213
substr str, r1, 1, repl
214
# if the replacement wasn't a carry, we're done
215
if orig < repl goto done
217
# if there are more characters in the range, increment those first
219
if r1 >= r0 goto inc_1
221
# insert a new character based on the previous one
222
unless repl == '0' goto extend_1
225
substr str, r0, 0, repl
234
Returns the identify value.
254
.include 'cclass.pasm'
264
.sub 'infix:===' :multi(String,String)
268
.tailcall 'prefix:?'($I0)
274
=head2 TODO Functions
280
This word is banned in Perl 6. You must specify units.
284
Needs to be in terms of StrPos, not Int.
292
Needs to be in terms of StrPos, not Int.
300
Should replace vec with declared arrays of bit, uint2, uint4, etc.
304
our List multi Str::words ( Rule $matcher = /\S+/, Str $input = $+_, Int $limit = inf )
305
our List multi Str::words ( Str $input : Rule $matcher = /\S+/, Int $limit = inf )
315
# vim: expandtab shiftwidth=4 ft=pir: