~ubuntu-branches/ubuntu/precise/rakudo/precise

« back to all changes in this revision

Viewing changes to src/classes/Str.pir

  • Committer: Bazaar Package Importer
  • Author(s): Ryan Niebur
  • Date: 2009-10-04 14:31:57 UTC
  • Revision ID: james.westby@ubuntu.com-20091004143157-ubq3wu0grk0f1e6a
Tags: upstream-0.1~2009.09
Import upstream version 0.1~2009.09

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=head1 TITLE
 
2
 
 
3
Str - Perl 6 Str class and related functions
 
4
 
 
5
=head1 DESCRIPTION
 
6
 
 
7
This file sets up the C<Perl6Str> PMC type (from F<src/pmc/perl6str.pmc>)
 
8
as the Perl 6 C<Str> class.
 
9
 
 
10
=head1 Methods
 
11
 
 
12
=over 4
 
13
 
 
14
=cut
 
15
 
 
16
.namespace ['Str']
 
17
 
 
18
.include 'cclass.pasm'
 
19
 
 
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)
 
27
 
 
28
    $P0 = get_hll_namespace ['Str']
 
29
    '!EXPORT'('sprintf', 'from'=>$P0)
 
30
.end
 
31
 
 
32
 
 
33
.sub 'ACCEPTS' :method
 
34
    .param string topic
 
35
    .tailcall 'infix:eq'(topic, self)
 
36
.end
 
37
 
 
38
 
 
39
=item perl()
 
40
 
 
41
Returns a Perl representation of the Str.
 
42
 
 
43
=cut
 
44
 
 
45
.sub 'perl' :method
 
46
    .local string str, result
 
47
    str = self
 
48
    result = '"'
 
49
    .local int pos
 
50
    pos = 0
 
51
    .local pmc arr
 
52
    arr = root_new ['parrot';'ResizablePMCArray']
 
53
  loop:
 
54
    .local string ch
 
55
    ch = substr str, pos, 1
 
56
    if ch == '' goto done
 
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
 
62
    goto loop_ch
 
63
  loop_nonprint:
 
64
    $I0 = is_cclass .CCLASS_PRINTING, ch, 0
 
65
    if $I0 goto loop_ch
 
66
    $I0 = ord ch
 
67
    arr[0] = $I0
 
68
    ch = sprintf '\x[%x]', arr
 
69
  loop_ch:
 
70
    result .= ch
 
71
    inc pos
 
72
    goto loop
 
73
  done:
 
74
    result .= '"'
 
75
    .return (result)
 
76
.end
 
77
 
 
78
 
 
79
=item sprintf( *@args )
 
80
 
 
81
=cut
 
82
 
 
83
.sub 'sprintf' :method
 
84
    .param pmc args            :slurpy
 
85
    args.'!flatten'()
 
86
    $P0 = new ['Str']
 
87
    push_eh args_fail
 
88
    sprintf $P0, self, args
 
89
    pop_eh
 
90
    .return ($P0)
 
91
  args_fail:
 
92
    pop_eh
 
93
    .tailcall '!FAIL'('Insufficient arguments supplied to sprintf')
 
94
.end
 
95
 
 
96
=item succ and pred
 
97
 
 
98
Increment and Decrement Methods
 
99
 
 
100
=cut
 
101
 
 
102
.namespace ['Str']
 
103
 
 
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).
 
119
 
 
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"
 
121
 
 
122
.sub '!range_pos' :anon
 
123
    .param string str
 
124
 
 
125
    .local int len, pos, r0, r1
 
126
    len = length str
 
127
 
 
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.
 
130
    pos = len
 
131
  scan_loop:
 
132
    # Reset range positions to indicate that we haven't found a valid substr
 
133
    r0 = 0
 
134
    r1 = -1
 
135
  scan_end_loop:
 
136
    unless pos > 0 goto done
 
137
    dec pos
 
138
    $S0 = substr str, pos, 1
 
139
    $I0 = index RANGES, $S0
 
140
    if $I0 < 0 goto scan_end_loop
 
141
 
 
142
    # we found a candidate end of the range, now scan for start
 
143
    r1 = pos
 
144
  scan_start_loop:
 
145
    # if we reach the beginning of the string, the range starts at pos 0
 
146
    unless pos > 0 goto done
 
147
    dec pos
 
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
 
155
    r0 = pos + 1
 
156
 
 
157
  done:
 
158
    .return (r0, r1)
 
159
.end
 
160
 
 
161
 
 
162
.sub 'pred' :method
 
163
    .local string str
 
164
    str = self
 
165
    str = clone str
 
166
 
 
167
    .local int r0, r1, ipos
 
168
    (r0, r1) = '!range_pos'(str)
 
169
    if r1 < 0 goto done
 
170
 
 
171
  dec_1:
 
172
    .local string orig, repl
 
173
    orig = substr str, r1, 1
 
174
    ipos = index RANGES, orig 
 
175
    $I0 = ipos + 1
 
176
    $I0 = index RANGES, orig, $I0
 
177
    if $I0 < 0 goto dec_2
 
178
    ipos = $I0
 
179
  dec_2:
 
180
    dec ipos
 
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
 
185
  carry:
 
186
    # if there are more characters in the range, decrement those first
 
187
    dec r1
 
188
    if r1 >= r0 goto dec_1
 
189
  extend:
 
190
    .tailcall '!FAIL'('Decrement out of range')
 
191
 
 
192
  done:
 
193
    .return (str)
 
194
.end
 
195
 
 
196
 
 
197
.sub 'succ' :method
 
198
    .local string str
 
199
    str = self
 
200
    str = clone str
 
201
 
 
202
    .local int r0, r1, ipos
 
203
    (r0, r1) = '!range_pos'(str)
 
204
    if r1 < 0 goto done
 
205
 
 
206
  inc_1:
 
207
    .local string orig, repl
 
208
    orig = substr str, r1, 1
 
209
    ipos = index RANGES, orig 
 
210
    inc ipos
 
211
    .local string repl
 
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
 
216
  carry:
 
217
    # if there are more characters in the range, increment those first
 
218
    dec r1
 
219
    if r1 >= r0 goto inc_1
 
220
  extend:
 
221
    # insert a new character based on the previous one
 
222
    unless repl == '0' goto extend_1
 
223
    repl = '1'
 
224
  extend_1:
 
225
    substr str, r0, 0, repl
 
226
 
 
227
  done:
 
228
    .return (str)
 
229
.end
 
230
 
 
231
 
 
232
=item WHICH()
 
233
 
 
234
Returns the identify value.
 
235
 
 
236
=cut
 
237
 
 
238
.sub 'WHICH' :method
 
239
    $S0 = self
 
240
    .return ($S0)
 
241
.end
 
242
 
 
243
 
 
244
=back
 
245
 
 
246
=head1 Functions
 
247
 
 
248
=over 4
 
249
 
 
250
=cut
 
251
 
 
252
.namespace []
 
253
 
 
254
.include 'cclass.pasm'
 
255
 
 
256
 
 
257
=item infix:===
 
258
 
 
259
Overridden for Str.
 
260
 
 
261
=cut
 
262
 
 
263
.namespace []
 
264
.sub 'infix:===' :multi(String,String)
 
265
    .param string a
 
266
    .param string b
 
267
    $I0 = iseq a, b
 
268
    .tailcall 'prefix:?'($I0)
 
269
.end
 
270
 
 
271
 
 
272
=back
 
273
 
 
274
=head2 TODO Functions
 
275
 
 
276
=over 4
 
277
 
 
278
=item length
 
279
 
 
280
This word is banned in Perl 6.  You must specify units.
 
281
 
 
282
=item index
 
283
 
 
284
Needs to be in terms of StrPos, not Int.
 
285
 
 
286
=item pack
 
287
 
 
288
=item quotemeta
 
289
 
 
290
=item rindex
 
291
 
 
292
Needs to be in terms of StrPos, not Int.
 
293
 
 
294
=item sprintf
 
295
 
 
296
=item unpack
 
297
 
 
298
=item vec
 
299
 
 
300
Should replace vec with declared arrays of bit, uint2, uint4, etc.
 
301
 
 
302
=item words
 
303
 
 
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 )
 
306
 
 
307
=back
 
308
 
 
309
=cut
 
310
 
 
311
# Local Variables:
 
312
#   mode: pir
 
313
#   fill-column: 100
 
314
# End:
 
315
# vim: expandtab shiftwidth=4 ft=pir: