Skip to content
Permalink
Newer
Older
100644 2866 lines (2651 sloc) 86.7 KB
Sep 5, 2014
1
;(function($B){
2
3
var _b_ = $B.builtins
Sep 5, 2014
4
5
// build tables from data in unicode_data.js
6
var unicode_tables = $B.unicode_tables
Sep 5, 2014
7
8
9
$B.has_surrogate = function(s){
10
// Check if there are "surrogate pairs" characters in string s
11
for(var i = 0; i < s.length; i++){
12
code = s.charCodeAt(i)
13
if(code >= 0xD800 && code <= 0xDBFF){
14
return true
15
}
16
}
17
return false
18
}
19
20
$B.String = function(s){
21
var codepoints = [],
22
index_map = {},
23
has_surrogate = false
24
for(var i = 0, len = s.length; i < len; i++){
25
index_map[codepoints.length] = i
26
var cp = s.codePointAt(i)
27
codepoints.push(cp)
28
if(cp >= 0x10000){
29
i++
30
has_surrogate = true
31
}
32
}
33
if(has_surrogate){
34
var res = new String(s)
35
res.__class__ = str
36
res.index_map = index_map
37
res.codepoints = codepoints
38
res.string = s
39
return res
40
}
41
return s
42
}
43
str
Feb 10, 2018
44
var str = {
Mar 19, 2018
45
__class__: _b_.type,
46
__dir__: _b_.object.__dir__,
47
$infos: {
48
__module__: "builtins",
49
__name__: "str"
50
},
str
Feb 10, 2018
51
$is_class: true,
Mar 19, 2018
52
$native: true
Sep 5, 2014
53
}
54
Mar 19, 2018
56
if($.start === null || $.start === _b_.None){$.start = 0}
57
else if($.start < 0){
58
$.start += $.self.length
59
$.start = Math.max(0, $.start)
60
}
61
if($.end === null || $.end === _b_.None){$.end = $.self.length}
62
else if($.end < 0){
63
$.end += $.self.length
64
$.end = Math.max(0, $.end)
65
}
67
if(! _b_.isinstance($.start, _b_.int) || ! _b_.isinstance($.end, _b_.int)){
Mar 19, 2018
68
throw _b_.TypeError.$factory("slice indices must be integers " +
69
"or None or have an __index__ method")
70
}
73
function reverse(s){
74
// Reverse a string
Mar 19, 2018
75
return s.split("").reverse().join("")
76
}
77
78
function check_str(obj, prefix){
Mar 19, 2018
79
if(! _b_.isinstance(obj, str)){
80
throw _b_.TypeError.$factory((prefix || '') +
81
"must be str, not " + $B.class_name(obj))
Mar 19, 2018
82
}
85
function to_chars(s){
86
// Transform Javascript string s into a list of Python characters
87
// (2 JS chars if surrogate, 1 otherwise)
88
var chars = []
89
for(var i = 0, len = s.length; i < len; i++){
90
var code = s.charCodeAt(i)
91
if(code >= 0xD800 && code <= 0xDBFF){
92
chars.push(s.substr(i, 2))
93
i++
94
}else{
95
chars.push(s.charAt(i))
96
}
97
}
98
return chars
99
}
100
101
function to_codepoints(s){
102
// Transform Javascript string s into a list of codepoints
103
if(s instanceof String){
104
return s.codepoints
105
}
106
var cps = []
107
for(var i = 0, len = s.length; i < len; i++){
108
var code = s.charCodeAt(i)
109
if(code >= 0xD800 && code <= 0xDBFF){
110
var v = 0x10000
111
v += (code & 0x03FF) << 10
112
v += (s.charCodeAt(i + 1) & 0x03FF)
113
cps.push(v)
114
i++
115
}else{
116
cps.push(code)
117
}
118
}
119
return cps
120
}
121
122
str.__add__ = function(self, other){
Mar 19, 2018
123
if(!(typeof other === "string")){
124
try{return $B.$getattr(other, "__radd__")(self)}
Mar 19, 2018
125
catch(err){
126
throw _b_.TypeError.$factory("Can't convert " +
127
$B.class_name(other) + " to str implicitly")}
Sep 5, 2014
128
}
Mar 19, 2018
129
return self + other
Sep 5, 2014
130
}
131
Mar 19, 2018
132
str.__contains__ = function(self, item){
133
if(! _b_.isinstance(item, str)){
Mar 19, 2018
134
throw _b_.TypeError.$factory("'in <string>' requires " +
135
"string as left operand, not " + item.__class__)
136
}
137
if(typeof item == "string"){
138
var nbcar = item.length
139
}else{
140
var nbcar = _b_.len(item)
141
}
142
if(nbcar == 0){
143
// a string contains the empty string
144
return true
145
}
146
if(self.length == 0){
147
return nbcar == 0
148
}
Mar 19, 2018
149
for(var i = 0, len = self.length; i < len; i++){
150
if(self.substr(i, nbcar) == item){
151
return true
152
}
Sep 5, 2014
153
}
154
return false
155
}
156
str
Feb 10, 2018
157
str.__delitem__ = function(){
158
throw _b_.TypeError.$factory("'str' object doesn't support item deletion")
Sep 5, 2014
159
}
160
Mar 19, 2018
161
// __dir__must be assigned explicitely because attribute resolution for
162
// builtin classes doesn't use __mro__
163
str.__dir__ = _b_.object.__dir__
165
str.__eq__ = function(self, other){
Mar 23, 2018
166
if(_b_.isinstance(other, _b_.str)){
167
return other.valueOf() == self.valueOf()
168
}
169
return _b_.NotImplemented
Sep 5, 2014
170
}
171
172
function preformat(self, fmt){
str
Feb 10, 2018
173
if(fmt.empty){return _b_.str.$factory(self)}
Mar 19, 2018
174
if(fmt.type && fmt.type != "s"){
175
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
176
"' for object of type 'str'")
178
return self
179
}
180
str
Feb 10, 2018
181
str.__format__ = function(self, format_spec) {
182
var fmt = new $B.parse_format_spec(format_spec)
Mar 19, 2018
183
if(fmt.sign !== undefined){
184
throw _b_.ValueError.$factory(
185
"Sign not allowed in string format specifier")
187
if(fmt.precision){
188
self = self.substr(0, fmt.precision)
189
}
190
// For strings, alignment default to left
Mar 19, 2018
191
fmt.align = fmt.align || "<"
192
return $B.format_width(preformat(self, fmt), fmt)
Sep 5, 2014
193
}
194
195
str.__getitem__ = function(self, arg){
196
var chars = to_chars(self)
197
if(_b_.isinstance(arg, _b_.int)){
Sep 5, 2014
198
var pos = arg
199
if(arg < 0){
200
pos += self.length
201
}
202
if(pos >= 0 && pos < chars.length){
203
return chars[pos]
204
}
Mar 19, 2018
205
throw _b_.IndexError.$factory("string index out of range")
206
}
207
if(_b_.isinstance(arg, _b_.slice)){
Mar 19, 2018
208
var s = _b_.slice.$conv_for_seq(arg, self.length),
209
start = s.start,
210
stop = s.stop,
211
step = s.step
212
var res = "",
Mar 19, 2018
213
i = null
Mar 19, 2018
214
if(step > 0){
215
if(stop <= start){
216
return ""
217
}
218
for(var i = start; i < stop; i += step){
219
res += chars[i]
220
}
Mar 23, 2018
221
}else{
222
if(stop >= start){
223
return ''
224
}
225
for(var i = start; i > stop; i += step){
226
res += chars[i]
227
}
Sep 5, 2014
229
return res
230
}
231
if(_b_.isinstance(arg, _b_.bool)){
232
return self.__getitem__(_b_.int.$factory(arg))
233
}
Mar 19, 2018
234
throw _b_.TypeError.$factory("string indices must be integers")
Sep 5, 2014
235
}
236
237
var prefix = 2,
238
suffix = 3,
Jun 12, 2020
239
mask = (2 ** 32 - 1),
240
str_hash_cache = {}
241
242
str.$nb_str_hash_cache = 0
Jun 12, 2020
243
244
function fnv(p){
245
if(p.length == 0){
246
return 0
247
}
Sep 5, 2014
248
249
var x = prefix
250
x = (x ^ (p[0] << 7)) & mask
251
for(var i = 0, len = p.length; i < len; i++){
252
x = ((1000003 * x) ^ p[i]) & mask
253
}
254
x = (x ^ p.length) & mask
255
x = (x ^ suffix) & mask
Sep 5, 2014
256
257
if(x == -1){
258
x = -2
259
}
260
return x
261
}
263
str.__hash__ = function(self) {
Jun 12, 2020
264
if(str_hash_cache[self] !== undefined){
265
return str_hash_cache[self]
266
}
267
str.$nb_str_hash_cache++
268
if(str.$nb_str_hash_cache > 100000){
269
// Avoid memory overflow
270
str.$nb_str_hash_cache = 0
271
str_hash_cache = {}
272
}
273
return str_hash_cache[self] = fnv(to_codepoints(self))
Sep 5, 2014
274
}
275
Mar 19, 2018
276
str.__init__ = function(self, arg){
Sep 5, 2014
277
self.valueOf = function(){return arg}
278
self.toString = function(){return arg}
Sep 5, 2014
280
}
281
282
var str_iterator = $B.make_iterator_class("str_iterator")
str
Feb 10, 2018
283
str.__iter__ = function(self){
284
return str_iterator.$factory(to_chars(self))
Sep 5, 2014
285
}
286
287
str.__len__ = function(self){
288
// found at
289
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length
290
if(self instanceof String){
291
return self.codepoints.length
292
}
293
return self.valueOf().length
Sep 5, 2014
295
296
// Start of section for legacy formatting (with %)
297
Mar 19, 2018
298
var kwarg_key = new RegExp("([^\\)]*)\\)")
299
300
var NotANumber = function() {
Mar 19, 2018
301
this.name = "NotANumber"
302
}
303
Mar 19, 2018
304
var number_check = function(s){
305
if(! _b_.isinstance(s, [_b_.int, _b_.float])){
306
throw new NotANumber()
307
}
308
}
309
Mar 19, 2018
310
var get_char_array = function(size, char){
311
if(size <= 0){
312
return ""
313
}
314
return new Array(size + 1).join(char)
315
}
316
Mar 19, 2018
317
var format_padding = function(s, flags, minus_one){
318
var padding = flags.padding
Mar 23, 2018
319
if(! padding){ // undefined
320
return s
321
}
322
s = s.toString()
323
padding = parseInt(padding, 10)
Mar 23, 2018
324
if(minus_one){ // numeric formatting where sign goes in front of padding
325
padding -= 1
326
}
Mar 19, 2018
327
if(! flags.left){
328
return get_char_array(padding - s.length, flags.pad_char) + s
Mar 19, 2018
329
}else{
330
// left adjusted
331
return s + get_char_array(padding - s.length, flags.pad_char)
332
}
333
}
334
Mar 19, 2018
335
var format_int_precision = function(val, flags){
336
var precision = flags.precision
Mar 19, 2018
337
if(!precision){
338
return val.toString()
339
}
340
precision = parseInt(precision, 10)
Mar 19, 2018
342
if(val.__class__ === $B.long_int){
343
s = $B.long_int.to_base(val, 10)
344
}else{
345
s = val.toString()
Mar 19, 2018
347
if(s[0] === "-"){
348
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
Mar 19, 2018
350
return get_char_array(precision - s.length, "0") + s
351
}
352
Mar 19, 2018
353
var format_float_precision = function(val, upper, flags, modifier){
354
var precision = flags.precision
355
// val is a float
Mar 19, 2018
356
if(isFinite(val)){
357
return modifier(val, precision, flags, upper)
Mar 19, 2018
359
if(val === Infinity){
360
val = "inf"
361
}else if(val === -Infinity){
362
val = "-inf"
363
}else{
364
val = "nan"
Mar 19, 2018
366
if(upper){
367
return val.toUpperCase()
368
}
369
return val
371
}
372
Mar 19, 2018
373
var format_sign = function(val, flags){
374
if(flags.sign){
375
if(val >= 0){
376
return "+"
Sep 5, 2014
377
}
Mar 19, 2018
378
}else if (flags.space){
379
if(val >= 0){
380
return " "
381
}
382
}
383
return ""
384
}
Sep 5, 2014
385
386
var str_format = function(val, flags) {
387
// string format supports left and right padding
388
flags.pad_char = " " // even if 0 padding is defined, don't use it
str
Feb 10, 2018
389
return format_padding(str.$factory(val), flags)
Sep 5, 2014
391
392
var num_format = function(val, flags) {
393
number_check(val)
Mar 19, 2018
394
if(val.__class__ === $B.long_int){
395
val = $B.long_int.to_base(val, 10)
396
}else{
397
val = parseInt(val)
400
var s = format_int_precision(val, flags)
Mar 19, 2018
401
if(flags.pad_char === "0"){
402
if(val < 0){
403
s = s.substring(1)
Mar 19, 2018
404
return "-" + format_padding(s, flags, true)
405
}
406
var sign = format_sign(val, flags)
Mar 19, 2018
407
if(sign !== ""){
408
return sign + format_padding(s, flags, true)
409
}
410
}
412
return format_padding(format_sign(val, flags) + s, flags)
413
}
Sep 5, 2014
414
415
var repr_format = function(val, flags) {
416
flags.pad_char = " " // even if 0 padding is defined, don't use it
417
return format_padding(_b_.repr(val), flags)
Sep 5, 2014
419
420
var ascii_format = function(val, flags) {
421
flags.pad_char = " " // even if 0 padding is defined, don't use it
422
return format_padding(_b_.ascii(val), flags)
Sep 5, 2014
424
425
// converts val to float and sets precision if missing
Mar 19, 2018
426
var _float_helper = function(val, flags){
427
number_check(val)
Mar 19, 2018
428
if(! flags.precision){
429
if(! flags.decimal_point){
430
flags.precision = 6
Mar 19, 2018
431
}else{
432
flags.precision = 0
433
}
Mar 19, 2018
434
}else{
435
flags.precision = parseInt(flags.precision, 10)
436
validate_precision(flags.precision)
437
}
438
return parseFloat(val)
439
}
Sep 5, 2014
440
441
// used to capture and remove trailing zeroes
Mar 19, 2018
442
var trailing_zeros = /(.*?)(0+)([eE].*)/,
443
leading_zeros = /\.(0*)/,
444
trailing_dot = /\.$/
Sep 5, 2014
445
446
var validate_precision = function(precision) {
447
// force precision to limits of javascript
Mar 19, 2018
448
if(precision > 20){precision = 20}
449
}
450
451
// gG
Mar 19, 2018
452
var floating_point_format = function(val, upper, flags){
453
val = _float_helper(val, flags),
454
v = val.toString(),
455
v_len = v.length,
456
dot_idx = v.indexOf('.')
457
if(dot_idx < 0){dot_idx = v_len}
458
if(val < 1 && val > -1){
459
var zeros = leading_zeros.exec(v),
460
numzeros
461
if(zeros){
462
numzeros = zeros[1].length
Mar 19, 2018
463
}else{
464
numzeros = 0
465
}
Mar 19, 2018
466
if(numzeros >= 4){
467
val = format_sign(val, flags) + format_float_precision(val, upper,
468
flags, _floating_g_exp_helper)
469
if(!flags.alternate){
470
var trl = trailing_zeros.exec(val)
Mar 19, 2018
471
if(trl){
472
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
474
}else{
475
if(flags.precision <= 1){
476
val = val[0] + "." + val.substring(1)
478
}
479
return format_padding(val, flags)
480
}
481
flags.precision = (flags.precision || 0) + numzeros
Mar 19, 2018
482
return format_padding(format_sign(val, flags) +
483
format_float_precision(val, upper, flags,
484
function(val, precision) {
485
return val.toFixed(_b_.min(precision, v_len - dot_idx) +
Mar 19, 2018
486
numzeros)
487
}),
488
flags
489
)
490
}
491
492
if(dot_idx > flags.precision){
493
val = format_sign(val, flags) + format_float_precision(val, upper,
494
flags, _floating_g_exp_helper)
495
if(! flags.alternate){
496
var trl = trailing_zeros.exec(val)
Mar 19, 2018
497
if(trl){
498
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
500
}else{
501
if(flags.precision <= 1){
502
val = val[0] + "." + val.substring(1)
503
}
504
}
505
return format_padding(val, flags)
506
}
Mar 19, 2018
507
return format_padding(format_sign(val, flags) +
508
format_float_precision(val, upper, flags,
509
function(val, precision) {
510
if(!flags.decimal_point){
511
precision = _b_.min(v_len - 1, 6)
Mar 19, 2018
512
}else if (precision > v_len){
513
if(! flags.alternate){
514
precision = v_len
515
}
Sep 5, 2014
516
}
Mar 19, 2018
517
if(precision < dot_idx){
518
precision = dot_idx
519
}
520
return val.toFixed(precision - dot_idx)
521
}),
522
flags
523
)
Sep 5, 2014
525
Mar 19, 2018
526
var _floating_g_exp_helper = function(val, precision, flags, upper){
527
if(precision){--precision}
528
val = val.toExponential(precision)
529
// pad exponent to two digits
Mar 19, 2018
530
var e_idx = val.lastIndexOf("e")
531
if(e_idx > val.length - 4){
532
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
534
if(upper){return val.toUpperCase()}
535
return val
536
}
537
538
// fF
539
var floating_point_decimal_format = function(val, upper, flags) {
540
val = _float_helper(val, flags)
Mar 19, 2018
541
return format_padding(format_sign(val, flags) +
542
format_float_precision(val, upper, flags,
543
function(val, precision, flags) {
544
val = val.toFixed(precision)
545
if(precision === 0 && flags.alternate){
546
val += '.'
547
}
548
return val
549
}),
550
flags
551
)
552
}
553
554
var _floating_exp_helper = function(val, precision, flags, upper) {
555
val = val.toExponential(precision)
556
// pad exponent to two digits
Mar 19, 2018
557
var e_idx = val.lastIndexOf("e")
Mar 23, 2018
558
if(e_idx > val.length - 4){
Mar 19, 2018
559
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
561
if(upper){return val.toUpperCase()}
562
return val
563
}
564
565
// eE
Mar 19, 2018
566
var floating_point_exponential_format = function(val, upper, flags){
567
val = _float_helper(val, flags)
Mar 19, 2018
569
return format_padding(format_sign(val, flags) +
570
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
571
}
572
Mar 19, 2018
573
var signed_hex_format = function(val, upper, flags){
575
number_check(val)
Mar 23, 2018
577
if(val.__class__ === $B.long_int){
Mar 19, 2018
578
ret = $B.long_int.to_base(val, 16)
579
}else{
580
ret = parseInt(val)
581
ret = ret.toString(16)
582
}
583
ret = format_int_precision(ret, flags)
Mar 19, 2018
584
if(upper){ret = ret.toUpperCase()}
Mar 23, 2018
585
if(flags.pad_char === "0"){
Mar 19, 2018
586
if(val < 0){
587
ret = ret.substring(1)
Mar 19, 2018
588
ret = "-" + format_padding(ret, flags, true)
589
}
590
var sign = format_sign(val, flags)
Mar 19, 2018
591
if(sign !== ""){
592
ret = sign + format_padding(ret, flags, true)
Sep 5, 2014
593
}
Mar 19, 2018
596
if(flags.alternate){
597
if(ret.charAt(0) === "-"){
598
if(upper){ret = "-0X" + ret.slice(1)}
599
else{ret = "-0x" + ret.slice(1)}
600
}else{
601
if(upper){ret = "0X" + ret}
602
else{ret = "0x" + ret}
603
}
604
}
605
return format_padding(format_sign(val, flags) + ret, flags)
606
}
Sep 5, 2014
607
608
var octal_format = function(val, flags) {
609
number_check(val)
Mar 19, 2018
612
if(val.__class__ === $B.long_int){
613
ret = $B.long_int.to_base(8)
614
}else{
615
ret = parseInt(val)
616
ret = ret.toString(8)
619
ret = format_int_precision(ret, flags)
Mar 19, 2018
621
if(flags.pad_char === "0"){
622
if(val < 0){
623
ret = ret.substring(1)
Mar 19, 2018
624
ret = "-" + format_padding(ret, flags, true)
625
}
626
var sign = format_sign(val, flags)
Mar 19, 2018
627
if(sign !== ""){
628
ret = sign + format_padding(ret, flags, true)
629
}
Sep 5, 2014
630
}
Mar 19, 2018
632
if(flags.alternate){
633
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
634
else{ret = "0o" + ret}
Sep 5, 2014
635
}
636
return format_padding(ret, flags)
637
}
638
639
function series_of_bytes(val, flags){
640
if(val.__class__ && val.__class__.$buffer_protocol){
641
var it = _b_.iter(val),
642
ints = []
643
while(true){
644
try{
645
ints.push(_b_.next(it))
646
}catch(err){
647
if(err.__class__ === _b_.StopIteration){
648
var b = _b_.bytes.$factory(ints)
649
return format_padding(_b_.bytes.decode(b, "ascii"), flags)
650
}
651
throw err
652
}
653
}
654
}else{
655
try{
656
bytes_obj = $B.$getattr(val, "__bytes__")
657
return format_padding(_b_.bytes.decode(bytes_obj), flags)
658
}catch(err){
659
if(err.__class__ === _b_.AttributeError){
660
throw _b_.TypeError.$factory("%b does not accept '" +
661
$B.class_name(val) + "'")
662
}
663
throw err
664
}
665
}
666
}
667
Mar 19, 2018
668
var single_char_format = function(val, flags){
669
if(_b_.isinstance(val, str) && val.length == 1){
671
}else if(_b_.isinstance(val, _b_.bytes) && val.source.length == 1){
672
val = val.source[0]
673
}else{
674
try{
675
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
676
}catch (err){
677
throw _b_.TypeError.$factory("%c requires int or char")
678
}
680
return format_padding(_b_.chr(val), flags)
681
}
682
Mar 19, 2018
683
var num_flag = function(c, flags){
684
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
685
flags.pad_char = "0"
686
return
687
}
Mar 19, 2018
688
if(!flags.decimal_point){
689
flags.padding = (flags.padding || "") + c
Mar 19, 2018
690
}else{
691
flags.precision = (flags.precision || "") + c
692
}
693
}
694
695
var decimal_point_flag = function(val, flags) {
Mar 23, 2018
696
if(flags.decimal_point){
697
// can only have one decimal point
698
throw new UnsupportedChar()
699
}
700
flags.decimal_point = true
701
}
702
Mar 19, 2018
703
var neg_flag = function(val, flags){
704
flags.pad_char = " " // overrides '0' flag
705
flags.left = true
706
}
707
Mar 19, 2018
708
var space_flag = function(val, flags){
709
flags.space = true
710
}
711
Mar 19, 2018
712
var sign_flag = function(val, flags){
713
flags.sign = true
714
}
715
Mar 19, 2018
716
var alternate_flag = function(val, flags){
717
flags.alternate = true
718
}
719
720
var char_mapping = {
Mar 19, 2018
722
"s": str_format,
723
"d": num_format,
724
"i": num_format,
725
"u": num_format,
726
"o": octal_format,
727
"r": repr_format,
728
"a": ascii_format,
729
"g": function(val, flags){
730
return floating_point_format(val, false, flags)
731
},
732
"G": function(val, flags){return floating_point_format(val, true, flags)},
733
"f": function(val, flags){
734
return floating_point_decimal_format(val, false, flags)
735
},
736
"F": function(val, flags){
737
return floating_point_decimal_format(val, true, flags)
738
},
739
"e": function(val, flags){
740
return floating_point_exponential_format(val, false, flags)
741
},
742
"E": function(val, flags){
743
return floating_point_exponential_format(val, true, flags)
744
},
745
"x": function(val, flags){return signed_hex_format(val, false, flags)},
746
"X": function(val, flags){return signed_hex_format(val, true, flags)},
747
"c": single_char_format,
748
"0": function(val, flags){return num_flag("0", flags)},
749
"1": function(val, flags){return num_flag("1", flags)},
750
"2": function(val, flags){return num_flag("2", flags)},
751
"3": function(val, flags){return num_flag("3", flags)},
752
"4": function(val, flags){return num_flag("4", flags)},
753
"5": function(val, flags){return num_flag("5", flags)},
754
"6": function(val, flags){return num_flag("6", flags)},
755
"7": function(val, flags){return num_flag("7", flags)},
756
"8": function(val, flags){return num_flag("8", flags)},
757
"9": function(val, flags){return num_flag("9", flags)},
758
"-": neg_flag,
759
" ": space_flag,
760
"+": sign_flag,
761
".": decimal_point_flag,
762
"#": alternate_flag
763
}
764
765
// exception thrown when an unsupported char is encountered in legacy format
Mar 19, 2018
766
var UnsupportedChar = function(){
767
this.name = "UnsupportedChar"
768
}
769
770
str.__mod__ = function(self, args){
771
var length = self.length,
Mar 19, 2018
772
pos = 0 | 0,
773
argpos = null,
774
getitem
Mar 19, 2018
775
if(_b_.isinstance(args, _b_.tuple)){
776
argpos = 0 | 0
778
getitem = $B.$getattr(args, "__getitem__", _b_.None)
779
}
780
var ret = ''
781
var $get_kwarg_string = function(s) {
782
// returns [self, newpos]
783
++pos
784
var rslt = kwarg_key.exec(s.substring(newpos))
Mar 19, 2018
785
if(! rslt){
786
throw _b_.ValueError.$factory("incomplete format key")
787
}
788
var key = rslt[1]
789
newpos += rslt[0].length
Mar 23, 2018
790
try{
791
var self = getitem(key)
Mar 19, 2018
792
}catch(err){
793
if(err.__class__ === _b_.KeyError){
794
throw err
795
}
796
throw _b_.TypeError.$factory("format requires a mapping")
798
return get_string_value(s, self)
799
}
800
801
var $get_arg_string = function(s) {
802
// returns [self, newpos]
803
var self
805
// non-tuple args
Mar 19, 2018
806
if(argpos === null){
807
// args is the value
Mar 19, 2018
809
}else{
810
self = args[argpos++]
Mar 19, 2018
811
if(self === undefined){
812
throw _b_.TypeError.$factory(
813
"not enough arguments for format string")
Sep 5, 2014
814
}
815
}
816
return get_string_value(s, self)
818
var get_string_value = function(s, self) {
819
// todo: get flags, type
820
// todo: string value based on flags, type, value
Mar 19, 2018
821
var flags = {"pad_char": " "}
822
do{
823
var func = char_mapping[s[newpos]]
Mar 23, 2018
824
try{
Mar 19, 2018
825
if(func === undefined){
826
throw new UnsupportedChar()
Mar 19, 2018
827
}else{
828
var ret = func(self, flags)
Mar 19, 2018
829
if(ret !== undefined){
830
return ret
831
}
832
++newpos
833
}
Mar 19, 2018
834
}catch (err){
835
if(err.name == "UnsupportedChar"){
836
invalid_char = s[newpos]
Mar 19, 2018
837
if(invalid_char === undefined){
838
throw _b_.ValueError.$factory("incomplete format")
Mar 19, 2018
840
throw _b_.ValueError.$factory(
841
"unsupported format character '" + invalid_char +
842
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
843
") at index " + newpos)
844
}else if(err.name === "NotANumber"){
845
var try_char = s[newpos],
846
cls = self.__class__
847
if(!cls){
848
if(typeof(self) === "string"){
849
cls = "str"
850
}else{
851
cls = typeof(self)
Mar 19, 2018
853
}else{
Mar 19, 2018
856
throw _b_.TypeError.$factory("%" + try_char +
857
" format: a number is required, not " + cls)
858
}else{
859
throw err
860
}
Sep 5, 2014
861
}
Mar 19, 2018
862
}while (true)
Sep 5, 2014
863
}
864
var nbph = 0 // number of placeholders
Mar 19, 2018
865
do{
866
var newpos = self.indexOf("%", pos)
867
if(newpos < 0){
868
ret += self.substring(pos)
869
break
870
}
871
ret += self.substring(pos, newpos)
872
++newpos
Mar 19, 2018
873
if(newpos < length){
874
if(self[newpos] === "%"){
875
ret += "%"
876
}else{
Mar 19, 2018
878
if(self[newpos] === "("){
879
++newpos
880
ret += $get_kwarg_string(self)
Mar 23, 2018
881
}else{
882
ret += $get_arg_string(self)
883
}
884
}
Mar 19, 2018
885
}else{
886
// % at end of string
887
throw _b_.ValueError.$factory("incomplete format")
888
}
889
pos = newpos + 1
Mar 19, 2018
890
}while(pos < length)
891
892
if(argpos !== null){
893
if(args.length > argpos){
894
throw _b_.TypeError.$factory(
895
"not enough arguments for format string")
896
}else if(args.length < argpos){
897
throw _b_.TypeError.$factory(
898
"not all arguments converted during string formatting")
Mar 19, 2018
900
}else if(nbph == 0){
901
throw _b_.TypeError.$factory(
902
"not all arguments converted during string formatting")
Sep 5, 2014
906
Sep 5, 2014
908
str
Feb 10, 2018
909
str.__mul__ = function(){
Mar 19, 2018
910
var $ = $B.args("__mul__", 2, {self: null, other: null},
911
["self", "other"], arguments, {}, null, null)
912
if(! _b_.isinstance($.other, _b_.int)){throw _b_.TypeError.$factory(
Mar 19, 2018
913
"Can't multiply sequence by non-int of type '" +
915
return $.self.valueOf().repeat($.other)
Sep 5, 2014
916
}
917
918
str.__ne__ = function(self, other){
919
return other !== self.valueOf()
920
}
Sep 5, 2014
921
922
function __newobj__(){
923
// __newobj__ is called with a generator as only argument
924
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
925
args = $.args
926
var res = args[1]
927
res.__class__ = args[0]
928
return res
929
}
930
931
str.__reduce_ex__ = function(self){
932
return $B.fast_tuple([
933
__newobj__,
934
$B.fast_tuple([self.__class__ || _b_.str, self]),
935
_b_.None,
936
_b_.None])
937
}
938
str
Feb 10, 2018
939
str.__repr__ = function(self){
941
var t = {
942
8: "\\x08",
943
9: "\\t",
944
10: "\\n",
945
11: "\\x0b",
946
12: "\\x0c",
947
13: "\\r",
948
92: "\\\\"
949
}
950
var repl = '',
951
chars = to_chars(self)
952
for(var i = 0; i < chars.length; i++){
953
var cp = _b_.ord(chars[i])
954
if(t[cp] !== undefined){
955
repl += t[cp]
956
}else if($B.is_unicode_cn(cp)){
957
var s = cp.toString(16)
958
while(s.length < 4){
959
s = '0' + s
960
}
961
repl += '\\u' + s
962
}else if(cp < 0x20 || (cp >= 0x7f && cp < 0xa0)){
963
cp = cp.toString(16)
964
if(cp.length < 2){
965
cp = '0' + cp
966
}
967
repl += '\\x' + cp
968
}else if(cp >= 0x300 && cp <= 0x36F){
969
repl += "\u200B" + chars[i]
Mar 19, 2018
975
if(res.search('"') == -1 && res.search("'") == -1){
976
return "'" + res + "'"
977
}else if(self.search('"') == -1){
978
return '"' + res + '"'
979
}
980
var qesc = new RegExp("'", "g") // to escape single quote
981
res = "'" + res.replace(qesc, "\\'") + "'"
Sep 5, 2014
982
return res
983
}
984
985
str.__rmul__ = function(self, other){
986
if(_b_.isinstance(other, _b_.int)){
987
other = _b_.int.numerator(other)
988
var res = ''
989
while(other > 0){
990
res += self
991
other--
992
}
993
return res
994
}
995
return _b_.NotImplemented
996
}
997
998
str.__setattr__ = function(self, attr, value){
999
if(typeof self === "string"){
1000
if(str.hasOwnProperty(attr)){
1001
throw _b_.AttributeError.$factory("'str' object attribute '" +
1002
attr + "' is read-only")
1003
}else{
1004
throw _b_.AttributeError.$factory(
1005
"'str' object has no attribute '" + attr + "'")
1006
}
1007
}
1008
// str subclass : use __dict__
1009
_b_.dict.$setitem(self.__dict__, attr, value)
1010
return $N
1011
}
1012
Mar 19, 2018
1013
str.__setitem__ = function(self, attr, value){
1014
throw _b_.TypeError.$factory(
1015
"'str' object does not support item assignment")
Sep 5, 2014
1016
}
Mar 27, 2019
1018
var combining = []
1019
for(var cp = 0x300; cp <= 0x36F; cp++){
1020
combining.push(String.fromCharCode(cp))
1021
}
1022
var combining_re = new RegExp("(" + combining.join("|") + ")", "g")
str
Feb 10, 2018
1024
str.__str__ = function(self){
1025
var repl = '',
1026
chars = to_chars(self)
1027
if(chars.length == self.length){
1028
return self.replace(combining_re, "\u200B$1")
1029
}
1030
for(var i = 0; i < chars.length; i++){
1031
var cp = _b_.ord(chars[i])
1032
if(cp >= 0x300 && cp <= 0x36F){
1033
repl += "\u200B" + chars[i]
1034
}else{
1035
repl += chars[i]
1036
}
1037
}
1038
return repl
Sep 5, 2014
1039
}
Mar 19, 2018
1041
str.toString = function(){return "string!"}
Sep 5, 2014
1042
1043
// generate comparison methods
1044
var $comp_func = function(self,other){
1045
if(typeof other !== "string"){return _b_.NotImplemented}
Sep 5, 2014
1046
return self > other
1047
}
Mar 19, 2018
1048
$comp_func += "" // source code
1049
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
Sep 5, 2014
1050
for(var $op in $comps){
Mar 19, 2018
1051
eval("str.__" + $comps[$op] + '__ = ' + $comp_func.replace(/>/gm,$op))
Sep 5, 2014
1052
}
1053
1054
// unsupported operations
Mar 19, 2018
1055
var $notimplemented = function(self, other){
1056
throw _b_.NotImplementedError.$factory(
Mar 19, 2018
1057
"OPERATOR not implemented for class str")
Sep 5, 2014
1058
}
1059
1060
str.capitalize = function(self){
1061
var $ = $B.args("capitalize", 1, {self}, ["self"],
1062
arguments, {}, null, null)
1063
if(self.length == 0){
1064
return ""
1065
}
1066
return self.charAt(0).toUpperCase() + self.substr(1)
1067
}
1068
1069
str.casefold = function(self){
1070
var $ = $B.args("casefold", 1, {self}, ["self"],
1071
arguments, {}, null, null),
1072
res = "",
1073
char,
1074
cf,
1075
chars = to_chars($.self)
1076
1077
for(var i = 0, len = chars.length; i < len; i++){
1078
char = chars[i]
1079
cf = $B.unicode_casefold[char]
1080
if(cf){
1081
cf.forEach(function(cp){
1082
res += String.fromCharCode(cp)
1083
})
1084
}else{
1086
}
1087
}
1088
return res
1089
}
Sep 5, 2014
1090
Mar 19, 2018
1091
str.center = function(){
1092
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
1093
["self", "width", "fillchar"],
1094
arguments, {fillchar:" "}, null, null),
1095
self = $.self
Mar 19, 2018
1097
if($.width <= self.length) {return self}
Mar 19, 2018
1099
var pad = parseInt(($.width - self.length) / 2),
1100
res = $.fillchar.repeat(pad)
Sep 5, 2014
1101
res += self + res
1102
if(res.length < $.width){
1103
res += $.fillchar
1104
}
Sep 5, 2014
1105
return res
1106
}
1107
str
Feb 10, 2018
1108
str.count = function(){
Mar 19, 2018
1109
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
1110
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
1112
if(!(typeof $.sub.valueOf() == "string")){
1113
throw _b_.TypeError.$factory("Can't convert '" + $B.class_name($.sub) +
1114
"' object to str implicitly")
1115
}
Mar 19, 2018
1117
if($.start !== null){
1119
if($.stop !== null){
1120
_slice = _b_.slice.$factory($.start, $.stop)
1121
}else{
1122
_slice = _b_.slice.$factory($.start, $.self.length)
1123
}
str
Feb 10, 2018
1124
substr = str.__getitem__.apply(null, [$.self].concat(_slice))
1126
if($.self.length + $.sub.length == 0){
1127
return 1
1128
}
Mar 19, 2018
1130
if($.sub.length == 0){
1131
if($.start == $.self.length){
1132
return 1
1133
}else if(substr.length == 0){
1134
return 0
1135
}
Mar 19, 2018
1136
return substr.length + 1
Mar 19, 2018
1138
var n = 0,
1139
pos = 0
1140
while(pos < substr.length){
1141
pos = substr.indexOf($.sub, pos)
1142
if(pos >= 0){
1143
n++
1144
pos += $.sub.length
1145
}else{
1146
break
1147
}
Sep 5, 2014
1148
}
1149
return n
1150
}
1151
1152
str.encode = function(){
1153
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
1154
["self", "encoding", "errors"], arguments,
1155
{encoding: "utf-8", errors: "strict"}, null, null)
1156
if($.encoding == "rot13" || $.encoding == "rot_13"){
1157
// Special case : returns a string
Mar 19, 2018
1158
var res = ""
1159
for(var i = 0, len = $.self.length; i < len ; i++){
1160
var char = $.self.charAt(i)
Mar 19, 2018
1161
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
1162
res += String.fromCharCode(String.charCodeAt(char) + 13)
1163
}else if(("m" < char && char <= "z") ||
1164
("M" < char && char <= "Z")){
1165
res += String.fromCharCode(String.charCodeAt(char) - 13)
1166
}else{res += char}
1167
}
1168
return res
1169
}
1170
return _b_.bytes.__new__(_b_.bytes, $.self, $.encoding, $.errors)
Sep 5, 2014
1171
}
1172
str
Feb 10, 2018
1173
str.endswith = function(){
1174
// Return True if the string ends with the specified suffix, otherwise
1175
// return False. suffix can also be a tuple of suffixes to look for.
1176
// With optional start, test beginning at that position. With optional
Sep 5, 2014
1177
// end, stop comparing at that position.
Mar 19, 2018
1178
var $ = $B.args("endswith", 4,
1179
{self:null, suffix:null, start:null, end:null},
Mar 19, 2018
1180
["self", "suffix", "start", "end"],
1181
arguments, {start: 0, end: null}, null, null)
Sep 20, 2015
1182
1183
normalize_start_end($)
1184
1185
var suffixes = $.suffix
1186
if(! _b_.isinstance(suffixes,_b_.tuple)){
1187
suffixes = [suffixes]
1188
}
1190
var chars = to_chars($.self),
1191
s = chars.slice($.start, $.end)
Mar 19, 2018
1192
for(var i = 0, len = suffixes.length; i < len; i++){
1193
var suffix = suffixes[i]
1194
if(! _b_.isinstance(suffix, str)){
1195
throw _b_.TypeError.$factory(
1196
"endswith first arg must be str or a tuple of str, not int")
1197
}
Mar 19, 2018
1198
if(suffix.length <= s.length &&
1199
s.slice(s.length - suffix.length).join('') == suffix){
1200
return true
1201
}
Sep 5, 2014
1202
}
1203
return false
1204
}
1205
str
Feb 10, 2018
1206
str.expandtabs = function(self, tabsize) {
Mar 19, 2018
1207
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1208
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1209
var s = $B.$GetInt($.tabsize),
1210
col = 0,
1211
pos = 0,
1212
res = "",
1213
chars = to_chars(self)
1214
if(s == 1){
1215
return self.replace(/\t/g," ")
1216
}
1217
while(pos < chars.length){
1218
var car = chars[pos]
Mar 19, 2018
1220
case "\t":
1221
while(col % s > 0){
1222
res += " ";
1223
col++
1224
}
Mar 19, 2018
1226
case "\r":
1227
case "\n":
1228
res += car
1229
col = 0
1230
break
1231
default:
1232
res += car
1233
col++
1234
break
1235
}
1236
pos++
1237
}
1238
return res
Sep 5, 2014
1239
}
1240
str
Feb 10, 2018
1241
str.find = function(){
1242
// Return the lowest index in the string where substring sub is found,
1243
// such that sub is contained in the slice s[start:end]. Optional
1244
// arguments start and end are interpreted as in slice notation.
Sep 5, 2014
1245
// Return -1 if sub is not found.
Mar 19, 2018
1246
var $ = $B.args("str.find", 4,
1247
{self: null, sub: null, start: null, end: null},
1248
["self", "sub", "start", "end"],
1249
arguments, {start: 0, end: null}, null, null)
1250
check_str($.sub)
1253
if(!_b_.isinstance($.start, _b_.int) ||
1254
!_b_.isinstance($.end, _b_.int)){
Mar 19, 2018
1255
throw _b_.TypeError.$factory("slice indices must be " +
1256
"integers or None or have an __index__ method")}
1257
// Can't use string.substring(start, end) because if end < start,
1258
// Javascript transforms it into substring(end, start)...
1259
var s = ""
1260
for(var i = $.start; i < $.end; i++){
1261
s += $.self.charAt(i)
1262
}
1264
var len = str.__len__($.self)
1265
1266
if($.sub.length == 0 && $.start == len){
1267
return len
1268
}
1269
if(s.length + $.sub.length == 0){
1270
return -1
1271
}
Mar 19, 2018
1273
var last_search = s.length - $.sub.length
1274
for(var i = 0; i <= last_search; i++){
1275
if(s.substr(i, $.sub.length) == $.sub){
1276
return $.start + str.__len__(s.substr(0, i))
1277
}
Sep 5, 2014
1278
}
Sep 5, 2014
1280
}
1281
1282
// Next function used by method .format()
1283
1284
$B.parse_format = function(fmt_string){
Sep 5, 2014
1285
1286
// Parse a "format string", as described in the Python documentation
1287
// Return a format object. For the format string
1288
// a.x[z]!r:...
1289
// the object has attributes :
1290
// - name : "a"
1291
// - name_ext : [".x", "[z]"]
1292
// - conv : r
1293
// - spec : rest of string after :
Sep 5, 2014
1294
Mar 19, 2018
1295
var elts = fmt_string.split(":"),
1296
name,
1297
conv,
1298
spec,
Mar 19, 2018
1299
name_ext = []
Mar 19, 2018
1300
if(elts.length == 1){
1301
// No : in the string : it only contains a name
1302
name = fmt_string
1303
}else{
1304
// name is before the first ":"
1305
// spec (the format specification) is after
1306
name = elts[0]
Mar 19, 2018
1307
spec = elts.splice(1).join(":")
Mar 19, 2018
1310
var elts = name.split("!")
1311
if(elts.length > 1){
1312
name = elts[0]
1313
conv = elts[1] // conversion flag
Sep 5, 2014
1315
Mar 19, 2018
1316
if(name !== undefined){
1317
// "name' may be a subscription or attribute
1318
// Put these "extensions" in the list "name_ext"
1319
function name_repl(match){
1320
name_ext.push(match)
Mar 19, 2018
1321
return ""
1322
}
1323
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1324
name = name.replace(name_ext_re, name_repl)
1325
}
Sep 5, 2014
1326
1327
return {name: name, name_ext: name_ext,
1328
conv: conv, spec: spec || "", string: fmt_string}
Sep 5, 2014
1330
1331
$B.split_format = function(self){
1332
// Parse self to detect formatting instructions
1333
// Create a list "parts" made of sections of the string :
1334
// - elements of even rank are literal text
1335
// - elements of odd rank are "format objects", built from the
1336
// format strings in self (of the form {...})
Mar 19, 2018
1337
var pos = 0,
1338
_len = self.length,
Mar 19, 2018
1340
text = "",
1341
parts = [],
1342
rank = 0
1343
while(pos < _len){
1344
car = self.charAt(pos)
Mar 21, 2018
1345
if(car == "{" && self.charAt(pos + 1) == "{"){
1346
// replace {{ by literal {
Mar 19, 2018
1347
text += "{"
1348
pos += 2
1349
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1350
// replace }} by literal }
Mar 19, 2018
1351
text += "}"
1352
pos += 2
1353
}else if(car == "{"){
1354
// Start of a format string
1356
// Store current literal text
1357
parts.push(text)
1358
1359
// Search the end of the format string, ie the } closing the
1360
// opening {. Since the string can contain other pairs {} for
1361
// nested formatting, an integer nb is incremented for each { and
1362
// decremented for each } ; the end of the format string is
Mar 19, 2018
1363
// reached when nb == 0
1364
var end = pos + 1,
1365
nb = 1
1366
while(end < _len){
1367
if(self.charAt(end) == "{"){nb++; end++}
1368
else if(self.charAt(end) == "}"){
1369
nb--; end++
1370
if(nb == 0){
1371
// End of format string
Mar 19, 2018
1372
var fmt_string = self.substring(pos + 1, end - 1)
1373
1374
// Create a format object, by function parse_format
1375
var fmt_obj = $B.parse_format(fmt_string)
1376
fmt_obj.raw_name = fmt_obj.name
1377
fmt_obj.raw_spec = fmt_obj.spec
1378
1379
// If no name is explicitely provided, use the rank
1380
if(!fmt_obj.name){
Mar 19, 2018
1381
fmt_obj.name = rank + ""
Sep 5, 2014
1384
Mar 19, 2018
1385
if(fmt_obj.spec !== undefined){
1386
// "spec" may contain "nested replacement fields"
1387
// Replace empty fields by the rank in positional
1388
// arguments
1389
function replace_nested(name, key){
1390
if(key == ""){
1391
// Use implicit rank
1392
return "{" + rank++ + "}"
1396
fmt_obj.spec = fmt_obj.spec.replace(/\{(.*?)\}/g,
1397
replace_nested)
1398
}
1400
// Store format object in list "parts"
1401
parts.push(fmt_obj)
Mar 19, 2018
1402
text = ""
1403
break
1404
}
1405
}else{end++}
Sep 5, 2014
1406
}
1407
if(nb > 0){
1408
throw _b_.ValueError.$factory("wrong format " + self)
1409
}
1411
}else{
1412
text += car
1413
pos++
1414
}
1415
}
1416
if(text){
1417
parts.push(text)
Sep 5, 2014
1418
}
1419
return parts
1420
}
1421
1422
str.format = function(self) {
1423
// Special management of keyword arguments if str.format is called by
1424
// str.format_map(mapping) : the argument "mapping" might not be a
1425
// dictionary
1426
var last_arg = $B.last(arguments)
1427
if(last_arg.$nat == "mapping"){
1428
var mapping = last_arg.mapping,
1429
getitem = $B.$getattr(mapping, "__getitem__")
1430
// Get the rest of the arguments
1431
var args = []
1432
for(var i = 0, len = arguments.length - 1; i < len; i++){
1433
args.push(arguments[i])
1434
}
1435
var $ = $B.args("format", 1, {self: null}, ["self"],
1436
args, {}, "$args", null)
1437
}else{
1438
var $ = $B.args("format", 1, {self: null}, ["self"],
1439
arguments, {}, "$args", "$kw"),
1440
mapping = $.$kw, // dictionary
1441
getitem = function(key){
1442
return _b_.dict.$getitem(mapping, key)
1443
}
1444
}
1445
var parts = $B.split_format($.self)
1446
1447
// Apply formatting to the values passed to format()
Mar 19, 2018
1448
var res = "",
1449
fmt
Mar 19, 2018
1451
for(var i = 0; i < parts.length; i++){
1452
// Literal text is added unchanged
Mar 19, 2018
1453
if(typeof parts[i] == "string"){res += parts[i]; continue}
1455
// Format objects
1456
fmt = parts[i]
1457
1458
if(fmt.spec !== undefined){
1459
// "spec" may contain "nested replacement fields"
1460
// In this case, evaluate them using the positional
1461
// or keyword arguments passed to format()
1462
function replace_nested(name, key){
1463
if(/\d+/.exec(key)){
1464
// If key is numeric, search in positional
1465
// arguments
1466
return _b_.tuple.__getitem__($.$args,
1467
parseInt(key))
1468
}else{
1469
// Else try in keyword arguments
1470
return _b_.dict.__getitem__($.$kw, key)
1471
}
1472
}
1473
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1474
replace_nested)
1475
}
Mar 21, 2018
1476
if(fmt.name.charAt(0).search(/\d/) > -1){
1477
// Numerical reference : use positional arguments
1478
var pos = parseInt(fmt.name),
Feb 11, 2018
1479
value = _b_.tuple.__getitem__($.$args, pos)
1480
}else{
1481
// Use keyword arguments
1482
var value = getitem(fmt.name)
1483
}
1484
// If name has extensions (attributes or subscriptions)
Mar 19, 2018
1485
for(var j = 0; j < fmt.name_ext.length; j++){
1486
var ext = fmt.name_ext[j]
Mar 19, 2018
1487
if(ext.charAt(0) == "."){
1489
value = $B.$getattr(value, ext.substr(1))
1490
}else{
1491
// Subscription
Mar 19, 2018
1492
var key = ext.substr(1, ext.length - 2)
1493
// An index made of digits is transformed into an integer
Mar 19, 2018
1494
if(key.charAt(0).search(/\d/) > -1){key = parseInt(key)}
1495
value = $B.$getattr(value, "__getitem__")(key)
Feb 12, 2018
1498
1499
// If the conversion flag is set, first call a function to convert
1500
// the value
Mar 19, 2018
1501
if(fmt.conv == "a"){value = _b_.ascii(value)}
1502
else if(fmt.conv == "r"){value = _b_.repr(value)}
1503
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1505
// Call attribute __format__ to perform the actual formatting
1506
if(value.$is_class || value.$factory){
1507
// For classes, don't use the class __format__ method
1508
res += value.__class__.__format__(value, fmt.spec)
1510
res += $B.$getattr(value, "__format__")(fmt.spec)
Sep 5, 2014
1512
}
Sep 5, 2014
1514
}
1515
1516
str.format_map = function(self, mapping){
1517
var $ = $B.args("format_map", 2, {self: null, mapping: null},
1518
['self', 'mapping'], arguments, {}, null, null)
1519
return str.format(self, {$nat: 'mapping', mapping})
Sep 5, 2014
1520
}
1521
str
Feb 10, 2018
1522
str.index = function(self){
Sep 5, 2014
1523
// Like find(), but raise ValueError when the substring is not found.
1524
var res = str.find.apply(null, arguments)
1525
if(res === -1){
1526
throw _b_.ValueError.$factory("substring not found")
1527
}
Sep 5, 2014
1528
return res
1529
}
1530
1531
str.isascii = function(self){
1532
/* Return true if the string is empty or all characters in the string are
1533
ASCII, false otherwise. ASCII characters have code points in the range
1534
U+0000-U+007F. */
1535
for(var i = 0, len = self.length; i < len; i++){
1536
if(self.charCodeAt(i) > 127){
1537
return false
1538
}
1539
}
1540
return true
1541
}
1542
1543
str.isalnum = function(self){
1544
/* Return true if all characters in the string are alphanumeric and there
1545
is at least one character, false otherwise. A character c is alphanumeric
1546
if one of the following returns True: c.isalpha(), c.isdecimal(),
1547
c.isdigit(), or c.isnumeric(). */
1548
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1549
arguments, {}, null, null),
1550
cp
1551
for(var char of to_chars(self)){
1552
cp = _b_.ord(char)
1553
if(unicode_tables.Ll[cp] ||
1554
unicode_tables.Lu[cp] ||
1555
unicode_tables.Lm[cp] ||
1556
unicode_tables.Lt[cp] ||
1557
unicode_tables.Lo[cp] ||
1558
unicode_tables.Nd[cp] ||
1559
unicode_tables.digits[cp] ||
1560
unicode_tables.numeric[cp]){
1561
continue
1562
}
1563
return false
1564
}
1565
return true
1566
}
1567
1568
str.isalpha = function(self){
1569
/* Return true if all characters in the string are alphabetic and there is
1570
at least one character, false otherwise. Alphabetic characters are those
1571
characters defined in the Unicode character database as "Letter", i.e.,
1572
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1573
or "Lo". */
1574
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1575
arguments, {}, null, null),
1576
cp
1577
for(var char of to_chars(self)){
1578
cp = _b_.ord(char)
1579
if(unicode_tables.Ll[cp] ||
1580
unicode_tables.Lu[cp] ||
1581
unicode_tables.Lm[cp] ||
1582
unicode_tables.Lt[cp] ||
1583
unicode_tables.Lo[cp]){
1584
continue
1585
}
1586
return false
1587
}
1588
return true
1589
}
1590
1591
str.isdecimal = function(self){
1592
/* Return true if all characters in the string are decimal characters and
1593
there is at least one character, false otherwise. Decimal characters are
1594
those that can be used to form numbers in base 10, e.g. U+0660,
1595
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1596
the Unicode General Category "Nd". */
1597
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1598
arguments, {}, null, null),
1599
cp
1600
for(var char of to_chars(self)){
1601
cp = _b_.ord(char)
1602
if(! unicode_tables.Nd[cp]){
1603
return false
1604
}
1605
}
1606
return self.length > 0
1607
}
1608
1609
str.isdigit = function(self){
1610
/* Return true if all characters in the string are digits and there is at
1611
least one character, false otherwise. */
1612
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1613
arguments, {}, null, null),
1614
cp
1615
for(var char of to_chars(self)){
1616
cp = _b_.ord(char)
1617
if(! unicode_tables.digits[cp]){
1618
return false
1619
}
1620
}
1621
return self.length > 0
1622
}
1623
1624
str.isidentifier = function(self){
1625
/* Return true if the string is a valid identifier according to the
1626
language definition. */
1627
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1629
if(self.length == 0){
1630
return false
1631
}
1632
var chars = to_chars(self)
1633
if(unicode_tables.XID_Start[_b_.ord(chars[0])] === undefined){
1636
for(var char of chars){
1637
var cp = _b_.ord(char)
1638
if(unicode_tables.XID_Continue[cp] === undefined){
1639
return false
1640
}
1641
}
1642
}
1643
return true
1644
}
1645
1646
str.islower = function(self){
1647
/* Return true if all cased characters 4 in the string are lowercase and
1648
there is at least one cased character, false otherwise. */
1649
var $ = $B.args("islower", 1, {self: null}, ["self"],
1650
arguments, {}, null, null),
1651
has_cased = false,
1654
for(var char of to_chars(self)){
1655
cp = _b_.ord(char)
1656
if(unicode_tables.Ll[cp]){
1657
has_cased = true
1658
continue
1659
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
1660
return false
1661
}
1662
}
1663
return has_cased
1664
}
1665
1666
str.isnumeric = function(self){
1667
/* Return true if all characters in the string are numeric characters, and
1668
there is at least one character, false otherwise. Numeric characters
1669
include digit characters, and all characters that have the Unicode numeric
1670
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1671
characters are those with the property value Numeric_Type=Digit,
1672
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1673
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1674
arguments, {}, null, null)
1675
for(var char of to_chars(self)){
1676
if(! unicode_tables.numeric[_b_.ord(char)]){
1677
return false
1678
}
1679
}
1680
return self.length > 0
1681
}
1682
1683
var unprintable = {},
1684
unprintable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1685
1686
str.isprintable = function(self){
1687
/* Return true if all characters in the string are printable or the string
1688
is empty, false otherwise. Nonprintable characters are those characters
1689
defined in the Unicode character database as "Other" or "Separator",
1690
excepting the ASCII space (0x20) which is considered printable. */
1691
1692
// Set unprintable if not set yet
1693
if(Object.keys(unprintable).length == 0){
1694
for(var i = 0; i < unprintable_gc.length; i++){
1695
var table = unicode_tables[unprintable_gc[i]]
1697
unprintable[cp] = true
1700
unprintable[32] = true
1701
}
1702
var $ = $B.args("isprintable", 1, {self: null}, ["self"],
1703
arguments, {}, null, null)
1704
for(var char of to_chars(self)){
1705
if(unprintable[_b_.ord(char)]){
1706
return false
1707
}
1708
}
1709
return true
1710
}
1711
1712
str.isspace = function(self){
1713
/* Return true if there are only whitespace characters in the string and
1714
there is at least one character, false otherwise.
1715
1716
A character is whitespace if in the Unicode character database, either its
1717
general category is Zs ("Separator, space"), or its bidirectional class is
1718
one of WS, B, or S.*/
1719
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1720
arguments, {}, null, null),
1721
cp
1722
for(var char of to_chars(self)){
1723
cp = _b_.ord(char)
1724
if(! unicode_tables.Zs[cp] &&
1725
$B.unicode_bidi_whitespace.indexOf(cp) == -1){
1726
return false
1727
}
1728
}
1729
return self.length > 0
1730
}
1731
1732
str.istitle = function(self){
1733
/* Return true if the string is a titlecased string and there is at least
1734
one character, for example uppercase characters may only follow uncased
1735
characters and lowercase characters only cased ones. Return false
1736
otherwise. */
1737
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1738
arguments, {}, null, null)
1739
return self.length > 0 && str.title(self) == self
1740
}
1741
1742
str.isupper = function(self){
1743
/* Return true if all cased characters 4 in the string are lowercase and
1744
there is at least one cased character, false otherwise. */
1745
var $ = $B.args("islower", 1, {self: null}, ["self"],
1746
arguments, {}, null, null),
1750
for(var char of to_chars(self)){
1751
cp = _b_.ord(char)
1752
if(unicode_tables.Lu[cp]){
1753
is_upper = true
1754
continue
1755
}else if(unicode_tables.Ll[cp] || unicode_tables.Lt[cp]){
str
Feb 10, 2018
1763
str.join = function(){
Mar 19, 2018
1764
var $ = $B.args("join", 2, {self: null, iterable: null},
Mar 19, 2018
1765
["self", "iterable"], arguments, {}, null, null)
Mar 19, 2018
1767
var iterable = _b_.iter($.iterable),
Mar 19, 2018
1768
res = [],
Sep 5, 2014
1770
while(1){
1771
try{
1772
var obj2 = _b_.next(iterable)
1773
if(! _b_.isinstance(obj2, str)){
1774
throw _b_.TypeError.$factory("sequence item " + count +
1775
": expected str instance, " + $B.class_name(obj2) +
1776
" found")
1777
}
1778
res.push(obj2)
Sep 5, 2014
1779
}catch(err){
1780
if(_b_.isinstance(err, _b_.StopIteration)){
1781
break
1782
}
Sep 5, 2014
1783
else{throw err}
1784
}
1785
}
1786
return res.join($.self)
Sep 5, 2014
1787
}
1788
str
Feb 10, 2018
1789
str.ljust = function(self) {
Mar 19, 2018
1790
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1791
["self", "width", "fillchar"],
1792
arguments, {fillchar: " "}, null, null),
1793
len = str.__len__(self)
1795
if($.width <= len){
1796
return self
1797
}
1798
return self + $.fillchar.repeat($.width - len)
Sep 5, 2014
1799
}
1800
1801
str.lower = function(self){
1802
var $ = $B.args("lower", 1, {self: null}, ["self"],
1803
arguments, {}, null, null)
1804
return self.toLowerCase()
1805
}
1806
1807
str.lstrip = function(self, x){
Mar 19, 2018
1808
var $ = $B.args("lstrip", 2, {self: null, chars: null}, ["self", "chars"],
1809
arguments, {chars:_b_.None}, null, null)
1810
if($.chars === _b_.None){
1811
return $.self.trimLeft()
1812
}
1813
var chars = to_chars(self)
1814
for(var i = 0, len = chars.length; i < len; i++){
1815
if($.chars.indexOf(chars[i]) === -1){
1816
return chars.slice(i).join('')
Mar 19, 2018
1819
return ""
Sep 5, 2014
1820
}
1821
1822
// note, maketrans should be a static function.
str
Feb 10, 2018
1823
str.maketrans = function() {
Mar 19, 2018
1824
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1825
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
Mar 19, 2018
1829
if($.y === null && $.z === null){
1830
// If there is only one argument, it must be a dictionary mapping
1831
// Unicode ordinals (integers) or characters (strings of length 1) to
1832
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1833
// keys will then be converted to ordinals.
Mar 19, 2018
1834
if(! _b_.isinstance($.x, _b_.dict)){
1835
throw _b_.TypeError.$factory(
1836
"maketrans only argument must be a dict")
Feb 11, 2018
1838
var items = _b_.list.$factory(_b_.dict.items($.x))
Mar 19, 2018
1839
for(var i = 0, len = items.length; i < len; i++){
1840
var k = items[i][0],
1841
v = items[i][1]
1842
if(! _b_.isinstance(k, _b_.int)){
1843
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1844
k = _b_.ord(k)
1845
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1846
" is not int or 1-char string")}
1847
}
Mar 19, 2018
1848
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1849
throw _b_.TypeError.$factory("dictionary value " + v +
1850
" is not None, integer or string")
1851
}
1852
_b_.dict.$setitem(_t, k, v)
1853
}
1854
return _t
1855
}else{
1856
// If there are two arguments, they must be strings of equal length,
1857
// and in the resulting dictionary, each character in x will be mapped
1858
// to the character at the same position in y
Mar 19, 2018
1859
if(! (_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1860
throw _b_.TypeError.$factory("maketrans arguments must be strings")
Mar 19, 2018
1861
}else if($.x.length !== $.y.length){
1862
throw _b_.TypeError.$factory(
1863
"maketrans arguments must be strings or same length")
1864
}else{
1865
var toNone = {}
Mar 19, 2018
1866
if($.z !== null){
1867
// If there is a third argument, it must be a string, whose
1868
// characters will be mapped to None in the result
Mar 19, 2018
1869
if(! _b_.isinstance($.z, _b_.str)){
1870
throw _b_.TypeError.$factory(
1871
"maketrans third argument must be a string")
Mar 19, 2018
1873
for(var i = 0, len = $.z.length; i < len; i++){
1874
toNone[_b_.ord($.z.charAt(i))] = true
1875
}
Mar 19, 2018
1877
for(var i = 0, len = $.x.length; i < len; i++){
1878
var key = _b_.ord($.x.charAt(i)),
1880
_b_.dict.$setitem(_t, key, value)
1881
}
1882
for(var k in toNone){
1883
_b_.dict.$setitem(_t, parseInt(k), _b_.None)
1884
}
1885
return _t
1886
}
1887
}
Sep 5, 2014
1888
}
1889
1890
str.maketrans.$type = "staticmethod"
1891
str
Feb 10, 2018
1892
str.partition = function() {
Mar 19, 2018
1893
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1894
arguments, {}, null, null)
1895
if($.sep == ""){
1896
throw _b_.ValueError.$factory("empty separator")
1897
}
Mar 19, 2018
1898
check_str($.sep)
1899
var chars = to_chars($.self),
1900
i = $.self.indexOf($.sep)
1901
if(i == -1){
1902
return _b_.tuple.$factory([$.self, "", ""])
1903
}
1904
return _b_.tuple.$factory([chars.slice(0, i).join(''), $.sep,
1905
chars.slice(i + $.sep.length).join('')])
Mar 19, 2018
1906
}
1907
1908
str.removeprefix = function(){
1909
var $ = $B.args("removeprefix", 2, {self: null, prefix: null},
1910
["self", "prefix"], arguments, {}, null, null)
1911
if(!_b_.isinstance($.prefix, str)){
1912
throw _b_.ValueError.$factory("prefix should be str, not " +
1913
`'${$B.class_name($.prefix)}'`)
1914
}
1915
if(str.startswith($.self, $.prefix)){
1916
return $.self.substr($.prefix.length)
1917
}
1918
return $.self.substr(0)
1919
}
1920
1921
str.removesuffix = function(){
1922
var $ = $B.args("removesuffix", 2, {self: null, prefix: null},
1923
["self", "suffix"], arguments, {}, null, null)
1924
if(!_b_.isinstance($.suffix, str)){
1925
throw _b_.ValueError.$factory("suffix should be str, not " +
1926
`'${$B.class_name($.prefix)}'`)
1927
}
1928
if($.suffix.length > 0 && str.endswith($.self, $.suffix)){
1929
return $.self.substr(0, $.self.length - $.suffix.length)
1930
}
1931
return $.self.substr(0)
1932
}
1933
Mar 19, 2018
1934
function $re_escape(str){
1935
var specials = "[.*+?|()$^"
1936
for(var i = 0, len = specials.length; i < len; i++){
1937
var re = new RegExp("\\"+specials.charAt(i), "g")
1938
str = str.replace(re, "\\"+specials.charAt(i))
1939
}
1940
return str
Sep 5, 2014
1941
}
1942
str
Feb 10, 2018
1943
str.replace = function(self, old, _new, count) {
1944
// Replaces occurrences of 'old' by '_new'. Count references
1945
// the number of times to replace. In CPython, negative or undefined
1946
// values of count means replace all.
Mar 19, 2018
1947
var $ = $B.args("replace", 4,
1948
{self: null, old: null, $$new: null, count: null},
1949
["self", "old", "$$new", "count"],
1950
arguments, {count: -1}, null, null),
1951
count = $.count,
1952
self = $.self,
1953
old = $.old,
1954
_new = $.$$new
1955
// Validate type of old
1956
check_str(old, "replace() argument 1 ")
1957
check_str(_new, "replace() argument 2 ")
1958
// Validate instance type of 'count'
1959
if(! _b_.isinstance(count,[_b_.int, _b_.float])){
1960
throw _b_.TypeError.$factory("'" + $B.class_name(count) +
Mar 19, 2018
1961
"' object cannot be interpreted as an integer")
1962
}else if(_b_.isinstance(count, _b_.float)){
Mar 19, 2018
1963
throw _b_.TypeError.$factory("integer argument expected, got float")
1964
}
1965
if(count == 0){
1966
return self
1967
}
1968
if(count.__class__ == $B.long_int){
1969
count = parseInt(count.value)
1970
}
Mar 19, 2018
1971
if(old == ""){
1972
if(_new == ""){
1973
return self
1974
}
1975
if(self == ""){
1976
return _new
1977
}
Mar 19, 2018
1978
var elts = self.split("")
1979
if(count > -1 && elts.length >= count){
1980
var rest = elts.slice(count).join("")
1981
return _new + elts.slice(0, count).join(_new) + rest
1982
}else{
1983
return _new + elts.join(_new) + _new
1984
}
Mar 19, 2018
1986
var elts = str.split(self, old, count)
Sep 5, 2014
1987
}
Mar 19, 2018
1989
var res = self,
1990
pos = -1
1991
if(old.length == 0){
Mar 19, 2018
1993
for(var i = 0; i < elts.length; i++){
1994
res += elts[i] + _new
Mar 19, 2018
1996
return res + rest
1999
if(count < 0){
2000
count = res.length
2001
}
Mar 19, 2018
2002
while(count > 0){
2003
pos = res.indexOf(old, pos)
2004
if(pos < 0){
2005
break
2006
}
Mar 19, 2018
2007
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
2008
pos = pos + _new.length
2009
count--
Mar 19, 2018
2011
return res
Sep 5, 2014
2012
}
2013
2014
str.rfind = function(self, substr){
2015
// Return the highest index in the string where substring sub is found,
2016
// such that sub is contained within s[start:end]. Optional arguments
Sep 5, 2014
2017
// start and end are interpreted as in slice notation. Return -1 on failure.
2018
if(arguments.length == 2 && typeof substr == "string"){
2019
return self.lastIndexOf(substr)
2020
}
Mar 19, 2018
2021
var $ = $B.args("rfind", 4,
Mar 19, 2018
2022
{self: null, sub: null, start: null, end: null},
2023
["self", "sub", "start", "end"],
2024
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
2025
2028
check_str($.sub)
Mar 19, 2018
2030
if($.sub.length == 0){
2031
if($.start > $.self.length){
2032
return -1
2033
}else{
2034
return str.__len__($.self)
2035
}
Mar 19, 2018
2040
for(var i = $.end - sublen; i >= $.start; i--){
2041
if($.self.substr(i, sublen) == $.sub){
2042
return str.__len__($.self.substr(0, i))
2043
}
Sep 5, 2014
2046
}
2047
str
Feb 10, 2018
2048
str.rindex = function(){
Sep 5, 2014
2049
// Like rfind() but raises ValueError when the substring sub is not found
Mar 19, 2018
2050
var res = str.rfind.apply(null, arguments)
2051
if(res == -1){
2052
throw _b_.ValueError.$factory("substring not found")
2053
}
Sep 5, 2014
2054
return res
2055
}
2056
str
Feb 10, 2018
2057
str.rjust = function(self) {
Mar 19, 2018
2058
var $ = $B.args("rjust",3,
2059
{self: null, width: null, fillchar: null},
2060
["self", "width", "fillchar"],
2061
arguments, {fillchar: " "}, null, null)
Sep 5, 2014
2062
2063
if($.width <= self.length){
2064
return self
2065
}
Sep 5, 2014
2066
2067
return $.fillchar.repeat($.width - self.length) + self
Sep 5, 2014
2068
}
2069
str
Feb 10, 2018
2070
str.rpartition = function(self,sep) {
Mar 19, 2018
2071
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
2072
arguments, {}, null, null)
2073
check_str($.sep)
2074
var self = reverse($.self),
2075
sep = reverse($.sep)
Mar 19, 2018
2076
var items = str.partition(self, sep).reverse()
2077
for(var i = 0; i < items.length; i++){
2078
items[i] = items[i].split("").reverse().join("")
2079
}
2080
return items
Sep 5, 2014
2081
}
2082
str
Feb 10, 2018
2083
str.rsplit = function(self) {
Mar 19, 2018
2084
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
2085
["self", "sep", "maxsplit"], arguments,
2086
{sep: _b_.None, maxsplit: -1}, null, null),
2087
sep = $.sep
2088
2089
// Use split on the reverse of the string and of separator
2090
var rev_str = reverse($.self),
2091
rev_sep = sep === _b_.None ? sep : reverse($.sep),
str
Feb 10, 2018
2092
rev_res = str.split(rev_str, rev_sep, $.maxsplit)
2094
// Reverse the list, then each string inside the list
2095
rev_res.reverse()
Mar 19, 2018
2096
for(var i = 0; i < rev_res.length; i++){
2097
rev_res[i] = reverse(rev_res[i])
Sep 5, 2014
2100
}
2101
Mar 19, 2018
2102
str.rstrip = function(self, x){
2103
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
Mar 19, 2018
2104
arguments, {chars: _b_.None}, null, null)
2105
if($.chars === _b_.None){
2106
return $.self.trimRight()
2107
}
2108
var chars = to_chars(self)
2109
for(var j = chars.length - 1; j >= 0; j--){
2110
if($.chars.indexOf(chars[j]) == -1){
2111
return chars.slice(0, j + 1).join('')
Mar 19, 2018
2114
return ""
Sep 5, 2014
2115
}
2116
str
Feb 10, 2018
2117
str.split = function(){
Mar 19, 2018
2118
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
2119
["self", "sep", "maxsplit"], arguments,
2120
{sep: _b_.None, maxsplit: -1}, null, null),
2121
sep = $.sep,
2122
maxsplit = $.maxsplit,
2123
self = $.self,
2124
pos = 0
2125
if(maxsplit.__class__ === $B.long_int){
2126
maxsplit = parseInt(maxsplit.value)
2127
}
2128
if(sep == ""){
2129
throw _b_.ValueError.$factory("empty separator")
2130
}
Mar 19, 2018
2131
if(sep === _b_.None){
Sep 5, 2014
2132
var res = []
2133
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){
2134
pos++
2135
}
2136
if(pos === self.length - 1){
2137
return [self]
2138
}
Mar 19, 2018
2139
var name = ""
Sep 5, 2014
2140
while(1){
Mar 19, 2018
2141
if(self.charAt(pos).search(/\s/) == -1){
2142
if(name == ""){
2143
name = self.charAt(pos)
2144
}else{
2145
name += self.charAt(pos)
2146
}
Sep 5, 2014
2147
}else{
Mar 19, 2018
2148
if(name !== ""){
Sep 5, 2014
2149
res.push(name)
Mar 19, 2018
2150
if(maxsplit !== -1 && res.length == maxsplit + 1){
Sep 5, 2014
2151
res.pop()
Mar 19, 2018
2152
res.push(name + self.substr(pos))
Sep 5, 2014
2153
return res
2154
}
Mar 19, 2018
2155
name = ""
Sep 5, 2014
2156
}
2157
}
2158
pos++
Mar 19, 2018
2159
if(pos > self.length - 1){
2160
if(name){
2161
res.push(name)
2162
}
Sep 5, 2014
2163
break
2164
}
2165
}
2166
return res
2167
}else{
Mar 19, 2018
2168
var res = [],
2169
s = "",
2170
seplen = sep.length
2171
if(maxsplit == 0){return [self]}
2172
while(pos < self.length){
2173
if(self.substr(pos, seplen) == sep){
Mar 19, 2018
2176
if(maxsplit > -1 && res.length >= maxsplit){
2177
res.push(self.substr(pos))
2178
return res
2179
}
Mar 19, 2018
2180
s = ""
2181
}else{
2182
s += self.charAt(pos)
2183
pos++
Sep 5, 2014
2184
}
2185
}
Sep 5, 2014
2188
}
2189
}
2190
2191
str.splitlines = function(self) {
2192
var $ = $B.args('splitlines', 2, {self: null, keepends: null},
2193
['self','keepends'], arguments, {keepends: false},
2194
null, null)
2195
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
2196
throw _b_.TypeError('integer argument expected, got '+
2197
$B.get_class($.keepends).__name)
2198
}
2199
var keepends = _b_.int.$factory($.keepends),
2200
res = [],
2201
self = $.self,
2202
start = 0,
2203
pos = 0
2204
if(!self.length){
2205
return res
2206
}
2208
if(self.substr(pos, 2) == '\r\n'){
2209
res.push(self.slice(start, keepends ? pos + 2 : pos))
2210
start = pos = pos+2
2211
}else if(self[pos] == '\r' || self[pos] == '\n'){
2212
res.push(self.slice(start, keepends ? pos+1 : pos))
2213
start = pos = pos+1
2214
}else{
2215
pos++
2216
}
2217
}
2218
if(start < self.length){
2219
res.push(self.slice(start))
2220
}
2221
return res
2222
}
Sep 5, 2014
2223
str
Feb 10, 2018
2224
str.startswith = function(){
2225
// Return True if string starts with the prefix, otherwise return False.
2226
// prefix can also be a tuple of prefixes to look for. With optional
2227
// start, test string beginning at that position. With optional end,
Sep 5, 2014
2228
// stop comparing string at that position.
Mar 19, 2018
2229
var $ = $B.args("startswith", 4,
2230
{self: null, prefix: null, start: null, end: null},
2231
["self", "prefix", "start", "end"],
2232
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
2233
2234
normalize_start_end($)
2235
2236
var prefixes = $.prefix
2237
if(! _b_.isinstance(prefixes, _b_.tuple)){
2238
prefixes = [prefixes]
2239
}
2241
var s = to_chars($.self).slice($.start, $.end).join('')
Mar 19, 2018
2242
for(var i = 0, len = prefixes.length; i < len; i++){
2243
var prefix = prefixes[i]
2244
if(! _b_.isinstance(prefix, str)){
2245
throw _b_.TypeError.$factory("endswith first arg must be str " +
2246
"or a tuple of str, not int")
2247
}
2248
if(s.substr(0, prefix.length) == prefix){
2249
return true
2250
}
Sep 5, 2014
2251
}
2252
return false
2253
}
2254
str
Feb 10, 2018
2255
str.strip = function(){
Mar 19, 2018
2256
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
2257
arguments, {chars: _b_.None}, null, null)
2258
if($.chars === _b_.None){
2259
return $.self.trim()
2260
}
2261
var chars = to_chars($.self)
2262
for(var i = 0; i < chars.length; i++){
2263
if($.chars.indexOf(chars[i]) == -1){
Mar 19, 2018
2264
break
2267
for(var j = chars.length - 1; j >= i; j--){
2268
if($.chars.indexOf(chars[j]) == -1){
Mar 19, 2018
2269
break
2272
return chars.slice(i, j + 1).join('')
Sep 5, 2014
2273
}
2274
2275
str.swapcase = function(self){
2276
var $ = $B.args("swapcase", 1, {self}, ["self"],
2277
arguments, {}, null, null),
2278
res = "",
2279
cp
2280
2281
for(var char of to_chars(self)){
2282
cp = _b_.ord(char)
2283
if(unicode_tables.Ll[cp]){
2284
res += char.toUpperCase()
2285
}else if(unicode_tables.Lu[cp]){
2286
res += char.toLowerCase()
2289
}
2290
}
2291
return res
2292
}
2293
2294
str.title = function(self){
2295
var $ = $B.args("title", 1, {self}, ["self"],
2296
arguments, {}, null, null),
2297
state,
2300
for(var char of to_chars(self)){
2301
cp = _b_.ord(char)
2302
if(unicode_tables.Ll[cp]){
2309
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
2310
res += state ? char.toLowerCase() : char
2311
state = "word"
2312
}else{
2313
state = null
2315
}
2316
}
2317
return res
2318
}
2319
2320
str.translate = function(self, table){
Mar 19, 2018
2321
var res = [],
2322
getitem = $B.$getattr(table, "__getitem__"),
2323
cp
2324
for(var char of to_chars(self)){
2325
cp = _b_.ord(char)
2328
if(repl !== _b_.None){
2329
if(typeof repl == "string"){
2330
res.push(repl)
2331
}else if(typeof repl == "number"){
2332
res.push(String.fromCharCode(repl))
2333
}
2334
}
2335
}catch(err){
Sep 5, 2014
2338
}
Mar 19, 2018
2339
return res.join("")
Sep 5, 2014
2340
}
2341
2342
str.upper = function(self){
2343
var $ = $B.args("upper", 1, {self: null}, ["self"],
2344
arguments, {}, null, null)
2345
return self.toUpperCase()
2346
}
2347
Mar 19, 2018
2348
str.zfill = function(self, width){
Mar 19, 2018
2349
var $ = $B.args("zfill", 2, {self: null, width: null},
2350
["self", "width"], arguments, {}, null, null),
2351
len = str.__len__(self)
2352
if($.width <= len){
2353
return self
2354
}
Mar 19, 2018
2356
case "+":
2357
case "-":
2358
return self.charAt(0) +
2359
"0".repeat($.width - len) + self.substr(1)
2361
return "0".repeat($.width - len) + self
Sep 5, 2014
2363
}
2364
2365
str.$factory = function(arg, encoding, errors){
2366
if(arguments.length == 0){
2367
return ""
2368
}
2370
return $B.UndefinedClass.__str__()
2371
}else if(arg === null){
2372
return '<Javascript null>'
2374
if(encoding !== undefined){
2375
// Arguments may be passed as keywords (cf. issue #1060)
2376
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2377
["arg", "encoding", "errors"], arguments,
2378
{encoding: "utf-8", errors: "strict"}, null, null),
2379
encoding = $.encoding,
2380
errors = $.errors
2381
}
2382
switch(typeof arg) {
Mar 19, 2018
2383
case "string":
Mar 27, 2019
2384
return str.__str__(arg)
Mar 19, 2018
2385
case "number":
2386
if(isFinite(arg)){return arg.toString()}
2389
if(arg.$is_class || arg.$factory){
2390
// arg is a class
2391
// In this case, str() doesn't use the attribute __str__ of the
2392
// class or its subclasses, but the attribute __str__ of the
2393
// class metaclass (usually "type") or its subclasses (usually
2394
// "object")
2395
// The metaclass is the attribute __class__ of the class dictionary
Mar 19, 2018
2396
var func = $B.$getattr(arg.__class__, "__str__")
2398
}
2400
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2401
encoding !== undefined){
2402
// str(bytes, encoding, errors) is equal to
2403
// bytes.decode(encoding, errors)
2404
return _b_.bytes.decode(arg, $.encoding, $.errors)
2406
// Implicit invocation of __str__ uses method __str__ on the class,
2407
// even if arg has an attribute __str__
2408
var klass = arg.__class__ || $B.get_class(arg)
2410
return $B.JSObj.__str__($B.JSObj.$factory(arg))
2412
var method = $B.$getattr(klass , "__str__", null)
2413
if(method === null ||
2414
// if not better than object.__str__, try __repr__
2415
(arg.__class__ && arg.__class__ !== _b_.object &&
2416
method.$infos && method.$infos.__func__ === _b_.object.__str__)){
2417
var method = $B.$getattr(klass, "__repr__")
Sep 5, 2014
2419
}
2420
catch(err){
2421
console.log("no __str__ for", arg)
Mar 19, 2018
2422
console.log("err ", err)
2423
if($B.debug > 1){console.log(err)}
2424
console.log("Warning - no method __str__ or __repr__, " +
2425
"default to toString", arg)
May 20, 2019
2426
throw err
Sep 5, 2014
2427
}
2428
return $B.$call(method)(arg)
Sep 5, 2014
2429
}
str
Feb 10, 2018
2430
2431
str.__new__ = function(cls){
Mar 19, 2018
2432
if(cls === undefined){
2433
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
Sep 5, 2014
2434
}
Mar 19, 2018
2435
return {__class__: cls}
Sep 5, 2014
2436
}
2437
str
Feb 10, 2018
2438
$B.set_func_names(str, "builtins")
Sep 5, 2014
2440
// dictionary and factory for subclasses of string
str
Feb 10, 2018
2441
var StringSubclass = $B.StringSubclass = {
Mar 19, 2018
2442
__class__: _b_.type,
2443
__mro__: [_b_.object],
2444
$infos: {
2445
__module__: "builtins",
2446
__name__: "str"
2447
},
str
Feb 10, 2018
2448
$is_class: true
Sep 5, 2014
2449
}
2450
str
Feb 10, 2018
2451
// the methods in subclass apply the methods in str to the
Sep 5, 2014
2452
// result of instance.valueOf(), which is a Javascript string
str
Feb 10, 2018
2453
for(var $attr in str){
Mar 19, 2018
2454
if(typeof str[$attr] == "function"){
Mar 19, 2018
2455
StringSubclass[$attr] = (function(attr){
Sep 5, 2014
2456
return function(){
Mar 19, 2018
2457
var args = [],
2458
pos = 0
2459
if(arguments.length > 0){
2460
var args = [arguments[0].valueOf()],
2461
pos = 1
2462
for(var i = 1, len = arguments.length; i < len; i++){
2463
args[pos++] = arguments[i]
Sep 5, 2014
2464
}
2465
}
Mar 19, 2018
2466
return str[attr].apply(null, args)
Sep 5, 2014
2467
}
2468
})($attr)
2469
}
2470
}
2471
str
Feb 10, 2018
2472
StringSubclass.__new__ = function(cls){
Sep 5, 2014
2475
str
Feb 10, 2018
2476
$B.set_func_names(StringSubclass, "builtins")
Sep 5, 2014
2478
_b_.str = str
2479
2480
// Function to parse the 2nd argument of format()
2481
$B.parse_format_spec = function(spec){
2482
if(spec == ""){
2483
this.empty = true
2484
}else{
Mar 19, 2018
2485
var pos = 0,
2486
aligns = "<>=^",
2487
digits = "0123456789",
2488
types = "bcdeEfFgGnosxX%",
2489
align_pos = aligns.indexOf(spec.charAt(0))
Mar 19, 2018
2490
if(align_pos != -1){
2491
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2492
// If the second char is also an alignment specifier, the
2493
// first char is the fill value
2494
this.fill = spec.charAt(0)
2495
this.align = spec.charAt(1)
2496
pos = 2
2497
}else{
2498
// The first character defines alignment : fill defaults to ' '
Mar 19, 2018
2499
this.align = aligns[align_pos]
2500
this.fill = " "
2501
pos++
2502
}
2503
}else{
2504
align_pos = aligns.indexOf(spec.charAt(1))
Mar 19, 2018
2505
if(spec.charAt(1) && align_pos != -1){
2506
// The second character defines alignment : fill is the first one
Mar 19, 2018
2507
this.align = aligns[align_pos]
2508
this.fill = spec.charAt(0)
2509
pos = 2
2510
}
2511
}
2512
var car = spec.charAt(pos)
Mar 19, 2018
2513
if(car == "+" || car == "-" || car == " "){
2514
this.sign = car
2515
pos++
2516
car = spec.charAt(pos)
2518
if(car == "#"){
2519
this.alternate = true; pos++; car = spec.charAt(pos)
2520
}
Mar 19, 2018
2521
if(car == "0"){
Mar 19, 2018
2522
// sign-aware : equivalent to fill = 0 and align == "="
Mar 19, 2018
2523
this.fill = "0"
2524
if(align_pos == -1){
2525
this.align = "="
2526
}
Mar 19, 2018
2527
pos++
2528
car = spec.charAt(pos)
2529
}
Mar 19, 2018
2530
while(car && digits.indexOf(car) > -1){
2531
if(this.width === undefined){
2532
this.width = car
2533
}else{
2534
this.width += car
2535
}
Mar 19, 2018
2536
pos++
2537
car = spec.charAt(pos)
2539
if(this.width !== undefined){
2540
this.width = parseInt(this.width)
2541
}
2542
if(this.width === undefined && car == "{"){
2543
// Width is determined by a parameter
2544
var end_param_pos = spec.substr(pos).search("}")
2545
this.width = spec.substring(pos, end_param_pos)
2546
console.log("width", "[" + this.width + "]")
2547
pos += end_param_pos + 1
2548
}
2549
if(car == ","){
2550
this.comma = true
2551
pos++
2552
car = spec.charAt(pos)
2553
}
Mar 19, 2018
2554
if(car == "."){
2555
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2556
throw _b_.ValueError.$factory(
2557
"Missing precision in format spec")
Mar 19, 2018
2559
this.precision = spec.charAt(pos + 1)
2560
pos += 2
2561
car = spec.charAt(pos)
2562
while(car && digits.indexOf(car) > -1){
Mar 21, 2018
2563
this.precision += car
Mar 19, 2018
2564
pos++
2565
car = spec.charAt(pos)
2566
}
2567
this.precision = parseInt(this.precision)
2568
}
Mar 19, 2018
2569
if(car && types.indexOf(car) > -1){
2570
this.type = car
2571
pos++
2572
car = spec.charAt(pos)
2573
}
2574
if(pos !== spec.length){
2575
throw _b_.ValueError.$factory("Invalid format specifier: " + spec)
2579
this.toString = function(){
Mar 19, 2018
2580
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2581
(this.align || "") +
2582
(this.sign || "") +
2583
(this.alternate ? "#" : "") +
2584
(this.sign_aware ? "0" : "") +
2585
(this.width || "") +
2586
(this.comma ? "," : "") +
2587
(this.precision ? "." + this.precision : "") +
2588
(this.type || "")
2589
}
2590
}
2591
2592
$B.format_width = function(s, fmt){
Mar 19, 2018
2593
if(fmt.width && s.length < fmt.width){
2594
var fill = fmt.fill || " ",
2595
align = fmt.align || "<",
2596
missing = fmt.width - s.length
2597
switch(align){
Mar 19, 2018
2598
case "<":
2599
return s + fill.repeat(missing)
2600
case ">":
2601
return fill.repeat(missing) + s
2602
case "=":
2603
if("+-".indexOf(s.charAt(0)) > -1){
2604
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2605
}else{
Mar 19, 2018
2606
return fill.repeat(missing) + s
Mar 19, 2018
2608
case "^":
2609
var left = parseInt(missing / 2)
2610
return fill.repeat(left) + s + fill.repeat(missing - left)
2611
}
2612
}
2613
return s
2614
}
2615
2616
function fstring_expression(){
Mar 19, 2018
2617
this.type = "expression"
2618
this.expression = ""
2619
this.conversion = null
2620
this.fmt = null
2621
}
2622
2623
function fstring_error(msg, pos){
2624
error = Error(msg)
2625
error.position = pos
2626
throw error
2627
}
2628
2629
$B.parse_fstring = function(string){
2630
// Parse a f-string
2631
var elts = [],
2632
pos = 0,
Mar 19, 2018
2633
current = "",
2634
ctype = null,
2635
nb_braces = 0,
2636
expr_start,
2637
car
2638
Mar 19, 2018
2639
while(pos < string.length){
2640
if(ctype === null){
2641
car = string.charAt(pos)
Mar 19, 2018
2642
if(car == "{"){
Mar 21, 2018
2643
if(string.charAt(pos + 1) == "{"){
Mar 19, 2018
2644
ctype = "string"
2645
current = "{"
2646
pos += 2
2647
}else{
Mar 19, 2018
2648
ctype = "expression"
2649
expr_start = pos + 1
2650
nb_braces = 1
2651
pos++
2652
}
Mar 19, 2018
2653
}else if(car == "}"){
Mar 21, 2018
2654
if(string.charAt(pos + 1) == car){
Mar 19, 2018
2655
ctype = "string"
2656
current = "}"
2657
pos += 2
2658
}else{
2659
fstring_error(" f-string: single '}' is not allowed",
2660
pos)
2661
}
2662
}else{
Mar 19, 2018
2663
ctype = "string"
2664
current = car
2665
pos++
Mar 19, 2018
2667
}else if(ctype == "string"){
2668
// end of string is the first single { or end of string
Mar 19, 2018
2669
var i = pos
2670
while(i < string.length){
2671
car = string.charAt(i)
Mar 19, 2018
2672
if(car == "{"){
Mar 21, 2018
2673
if(string.charAt(i + 1) == "{"){
Mar 19, 2018
2674
current += "{"
2675
i += 2
2676
}else{
2677
elts.push(current)
Mar 19, 2018
2678
ctype = "expression"
2679
expr_start = i + 1
Mar 19, 2018
2680
pos = i + 1
2681
break
2682
}
Mar 19, 2018
2683
}else if(car == "}"){
2684
if(string.charAt(i + 1) == car){
2685
current += car
2686
i += 2
2687
}else{
2688
fstring_error(" f-string: single '}' is not allowed",
2689
pos)
2690
}
2691
}else{
2692
current += car
2693
i++
2694
}
2695
}
Mar 19, 2018
2696
pos = i + 1
2697
}else if(ctype == "debug"){
2698
// after the equal sign, whitespace are ignored and the only
2699
// valid characters are } and :
2700
while(string.charAt(i) == " "){i++}
2701
if(string.charAt(i) == "}"){
2702
// end of debug expression
2703
console.log('end of debug', current)
2704
elts.push(current)
2705
ctype = null
2706
current = ""
2707
pos = i + 1
2708
}
2709
}else{
2710
// End of expression is the } matching the opening {
2711
// There may be nested braces
2712
var i = pos,
2713
nb_braces = 1,
2714
nb_paren = 0,
2715
current = new fstring_expression()
Mar 19, 2018
2716
while(i < string.length){
2717
car = string.charAt(i)
Mar 19, 2018
2718
if(car == "{" && nb_paren == 0){
2719
nb_braces++
2720
current.expression += car
2721
i++
Mar 19, 2018
2722
}else if(car == "}" && nb_paren == 0){
2723
nb_braces -= 1
Mar 19, 2018
2724
if(nb_braces == 0){
2725
// end of expression
2726
if(current.fmt){
2727
current.format = string.substring(fmt_start, i)
2728
}
2729
if(current.expression == ""){
2730
fstring_error("f-string: empty expression not allowed",
2731
pos)
2732
}
2733
elts.push(current)
2734
ctype = null
Mar 19, 2018
2735
current = ""
2736
pos = i + 1
2739
current.expression += car
2740
i++
Mar 19, 2018
2741
}else if(car == "\\"){
2742
// backslash is not allowed in expressions
2743
throw Error("f-string expression part cannot include a" +
2744
" backslash")
Mar 19, 2018
2745
}else if(nb_paren == 0 && car == "!" && current.fmt === null &&
2746
":}".indexOf(string.charAt(i + 2)) > -1){
Mar 19, 2018
2747
if(current.expression.length == 0){
2748
throw Error("f-string: empty expression not allowed")
2749
}
Mar 19, 2018
2750
if("ars".indexOf(string.charAt(i + 1)) == -1){
2751
throw Error("f-string: invalid conversion character:" +
2752
" expected 's', 'r', or 'a'")
2753
}else{
Mar 19, 2018
2754
current.conversion = string.charAt(i + 1)
2755
i += 2
2756
}
Mar 19, 2018
2757
}else if(car == "("){
2758
nb_paren++
2759
current.expression += car
2760
i++
Mar 19, 2018
2761
}else if(car == ")"){
2762
nb_paren--
2763
current.expression += car
2764
i++
Mar 19, 2018
2765
}else if(car == '"'){
2766
// triple string ?
Mar 19, 2018
2767
if(string.substr(i, 3) == '"""'){
2768
var end = string.indexOf('"""', i + 3)
2769
if(end == -1){
2770
fstring_error("f-string: unterminated string", pos)
Mar 19, 2018
2771
}else{
2772
var trs = string.substring(i, end + 3)
2773
trs = trs.replace("\n", "\\n\\")
2774
current.expression += trs
Mar 19, 2018
2775
i = end + 3
2776
}
2777
}else{
Mar 19, 2018
2778
var end = string.indexOf('"', i + 1)
2779
if(end == -1){
2780
fstring_error("f-string: unterminated string", pos)
Mar 19, 2018
2781
}else{
2782
current.expression += string.substring(i, end + 1)
2783
i = end + 1
2784
}
2785
}
Mar 19, 2018
2786
}else if(nb_paren == 0 && car == ":"){
2787
current.fmt = true
2788
var fmt_start = i
2789
current.expression += car
2790
i++
2791
}else if(car == "="){
2792
// might be a "debug expression", eg f"{x=}"
2793
var ce = current.expression,
2794
last_char = ce.charAt(ce.length - 1),
2795
last_char_re = ('()'.indexOf(last_char) > -1 ? "\\" : "") + last_char
2799
string.charAt(i + 1) == "=" ||
2800
"=!<>:".search(last_char_re) > -1){
2801
// not a debug expression
2804
}else{
2805
// add debug string
2806
tail = car
2807
while(string.charAt(i + 1).match(/\s/)){
2808
tail += string.charAt(i + 1)
2809
i++
2810
}
2811
// push simple string
2812
elts.push(current.expression + tail)
2813
// remove trailing whitespace from expression
2814
while(ce.match(/\s$/)){
2815
ce = ce.substr(0, ce.length - 1)
2816
}
2817
current.expression = ce
2818
ctype = "debug"
2819
i++
2820
}
2821
}else{
2822
current.expression += car
2823
i++
2824
}
2825
}
Mar 21, 2018
2826
if(nb_braces > 0){
2827
fstring_error("f-string: expected '}'", pos)
2828
}
2829
}
2830
}
2831
if(current.length > 0){
2832
elts.push(current)
2833
}
2834
for(var elt of elts){
2835
if(typeof elt == "object"){
2836
if(elt.fmt_pos !== undefined &&
2837
elt.expression.charAt(elt.fmt_pos) != ':'){
2838
console.log('mauvais format', string, elts)
2839
throw Error()
2840
}
2841
}
2842
}
2843
return elts
2844
}
2845
2846
var _chr = $B.codepoint2jsstring = function(i){
2847
if(i >= 0x10000 && i <= 0x10FFFF){
2848
var code = (i - 0x10000)
2849
return String.fromCodePoint(0xD800 | (code >> 10)) +
2850
String.fromCodePoint(0xDC00 | (code & 0x3FF))
2851
}else{
2852
return String.fromCodePoint(i)
2853
}
2854
}
2856
var _ord = $B.jsstring2codepoint = function(c){
2857
if(c.length == 1){
2858
return c.charCodeAt(0)
2859
}
2860
var code = 0x10000
2861
code += (c.charCodeAt(0) & 0x03FF) << 10
2862
code += (c.charCodeAt(1) & 0x03FF)
2863
return code
2864
}
2865
Sep 5, 2014
2866
})(__BRYTHON__)