@@ -133,6 +133,7 @@ struct Frame {
133
133
134
134
/* * Used for accumulating a joined string. */
135
135
UString str;
136
+ bool first;
136
137
137
138
/* * The context is used in error messages to attempt to find a reasonable name for the
138
139
* object, function, or thunk value being executed. If it is a thunk, it is filled
@@ -1330,12 +1331,12 @@ class Interpreter {
1330
1331
const auto *str = static_cast <const HeapString *>(args[0 ].v .h );
1331
1332
const auto *c = static_cast <const HeapString *>(args[1 ].v .h );
1332
1333
long maxsplits = long (args[2 ].v .d );
1333
- int start = 0 ;
1334
- int test = 0 ;
1334
+ unsigned start = 0 ;
1335
+ unsigned test = 0 ;
1335
1336
scratch = makeArray ({});
1336
1337
auto &elements = static_cast <HeapArray *>(scratch.v .h )->elements ;
1337
1338
while (test < str->value .size () && (maxsplits == -1 ||
1338
- maxsplits > elements.size ())) {
1339
+ size_t ( maxsplits) > elements.size ())) {
1339
1340
if (c->value [0 ] == str->value [test]) {
1340
1341
auto *th = makeHeap<HeapThunk>(idArrayElement, nullptr , 0 , nullptr );
1341
1342
elements.push_back (th);
@@ -1359,14 +1360,20 @@ class Interpreter {
1359
1360
const auto *str = static_cast <const HeapString *>(args[0 ].v .h );
1360
1361
long from = long (args[1 ].v .d );
1361
1362
long len = long (args[2 ].v .d );
1362
- if (len + from > str->value .size ()) {
1363
- len = str->value .size () - from;
1363
+ if (from < 0 ) {
1364
+ std::stringstream ss;
1365
+ ss << " substr second parameter should be greater than zero, got " << from;
1366
+ throw makeError (loc, ss.str ());
1364
1367
}
1365
- if (len <= 0 ) {
1366
- scratch = makeString (U" " );
1367
- } else {
1368
- scratch = makeString (str->value .substr (from, len));
1368
+ if (len < 0 ) {
1369
+ std::stringstream ss;
1370
+ ss << " substr third parameter should be greater than zero, got " << len;
1371
+ throw makeError (loc, ss.str ());
1372
+ }
1373
+ if (size_t (len + from) > str->value .size ()) {
1374
+ len = str->value .size () - from;
1369
1375
}
1376
+ scratch = makeString (str->value .substr (from, len));
1370
1377
return nullptr ;
1371
1378
}
1372
1379
@@ -1416,7 +1423,7 @@ class Interpreter {
1416
1423
validateBuiltinArgs (loc, " asciiLower" , args, {Value::STRING});
1417
1424
const auto *str = static_cast <const HeapString *>(args[0 ].v .h );
1418
1425
UString new_str (str->value );
1419
- for (int i = 0 ; i < new_str.size (); ++i) {
1426
+ for (size_t i = 0 ; i < new_str.size (); ++i) {
1420
1427
if (new_str[i] >= ' A' && new_str[i] <= ' Z' ) {
1421
1428
new_str[i] = new_str[i] - ' A' + ' a' ;
1422
1429
}
@@ -1430,7 +1437,7 @@ class Interpreter {
1430
1437
validateBuiltinArgs (loc, " asciiUpper" , args, {Value::STRING});
1431
1438
const auto *str = static_cast <const HeapString *>(args[0 ].v .h );
1432
1439
UString new_str (str->value );
1433
- for (int i = 0 ; i < new_str.size (); ++i) {
1440
+ for (size_t i = 0 ; i < new_str.size (); ++i) {
1434
1441
if (new_str[i] >= ' a' && new_str[i] <= ' z' ) {
1435
1442
new_str[i] = new_str[i] - ' a' + ' A' ;
1436
1443
}
@@ -1508,7 +1515,7 @@ class Interpreter {
1508
1515
}
1509
1516
}
1510
1517
1511
- void joinString (UString &running, const Value &sep, unsigned idx, const Value &elt)
1518
+ void joinString (bool &first, UString &running, const Value &sep, unsigned idx, const Value &elt)
1512
1519
{
1513
1520
if (elt.t == Value::NULL_TYPE) {
1514
1521
return ;
@@ -1518,39 +1525,33 @@ class Interpreter {
1518
1525
ss << " expected string but arr[" << idx << " ] was " << type_str (elt);
1519
1526
throw makeError (stack.top ().location , ss.str ());
1520
1527
}
1521
- if (!running. empty () ) {
1528
+ if (!first ) {
1522
1529
running.append (static_cast <HeapString *>(sep.v .h )->value );
1523
1530
}
1531
+ first = false ;
1524
1532
running.append (static_cast <HeapString *>(elt.v .h )->value );
1525
1533
}
1526
1534
1527
- const AST *joinStrings (const Value &sep, const Value &arr, unsigned idx, UString running )
1535
+ const AST *joinStrings (void )
1528
1536
{
1529
- const auto & elements = static_cast <HeapArray*>(arr.v .h )->elements ;
1530
- if (idx >= elements.size ()) {
1531
- scratch = makeString (running);
1532
- } else {
1533
- for (int i = idx; i < elements.size (); ++i) {
1534
- auto *th = elements[i];
1535
- if (th->filled ) {
1536
- joinString (running, sep, i, th->content );
1537
- } else {
1538
- Frame &f = stack.top ();
1539
- f.kind = FRAME_BUILTIN_JOIN_STRINGS;
1540
- f.val = sep;
1541
- f.val2 = arr;
1542
- f.str = running;
1543
- f.elementId = i;
1544
- stack.newCall (f.location , th, th->self , th->offset , th->upValues );
1545
- return th->body ;
1546
- }
1537
+ Frame &f = stack.top ();
1538
+ const auto & elements = static_cast <HeapArray*>(f.val2 .v .h )->elements ;
1539
+ while (f.elementId < elements.size ()) {
1540
+ auto *th = elements[f.elementId ];
1541
+ if (th->filled ) {
1542
+ joinString (f.first , f.str , f.val , f.elementId , th->content );
1543
+ f.elementId ++;
1544
+ } else {
1545
+ stack.newCall (f.location , th, th->self , th->offset , th->upValues );
1546
+ return th->body ;
1547
1547
}
1548
- scratch = makeString (running);
1549
1548
}
1549
+ scratch = makeString (f.str );
1550
1550
return nullptr ;
1551
1551
}
1552
1552
1553
- void joinArray (std::vector<HeapThunk*> &running, const Value &sep, unsigned idx, const Value &elt)
1553
+ void joinArray (bool &first, std::vector<HeapThunk*> &running, const Value &sep, unsigned idx,
1554
+ const Value &elt)
1554
1555
{
1555
1556
if (elt.t == Value::NULL_TYPE) {
1556
1557
return ;
@@ -1560,37 +1561,30 @@ class Interpreter {
1560
1561
ss << " expected array but arr[" << idx << " ] was " << type_str (elt);
1561
1562
throw makeError (stack.top ().location , ss.str ());
1562
1563
}
1563
- if (!running. empty () ) {
1564
+ if (!first ) {
1564
1565
auto & elts = static_cast <HeapArray *>(sep.v .h )->elements ;
1565
1566
running.insert (running.end (), elts.begin (), elts.end ());
1566
1567
}
1568
+ first = false ;
1567
1569
auto & elts = static_cast <HeapArray *>(elt.v .h )->elements ;
1568
1570
running.insert (running.end (), elts.begin (), elts.end ());
1569
1571
}
1570
1572
1571
- const AST *joinArrays (const Value &sep, const Value &arr, unsigned idx, std::vector<HeapThunk*> &running )
1573
+ const AST *joinArrays (void )
1572
1574
{
1573
- const auto & elements = static_cast <HeapArray*>(arr.v .h )->elements ;
1574
- if (idx >= elements.size ()) {
1575
- scratch = makeArray (running);
1576
- } else {
1577
- for (int i = idx; i < elements.size (); ++i) {
1578
- auto *th = elements[i];
1579
- if (th->filled ) {
1580
- joinArray (running, sep, i, th->content );
1581
- } else {
1582
- Frame &f = stack.top ();
1583
- f.kind = FRAME_BUILTIN_JOIN_ARRAYS;
1584
- f.val = sep;
1585
- f.val2 = arr;
1586
- f.thunks = running;
1587
- f.elementId = i;
1588
- stack.newCall (f.location , th, th->self , th->offset , th->upValues );
1589
- return th->body ;
1590
- }
1575
+ Frame &f = stack.top ();
1576
+ const auto & elements = static_cast <HeapArray*>(f.val2 .v .h )->elements ;
1577
+ while (f.elementId < elements.size ()) {
1578
+ auto *th = elements[f.elementId ];
1579
+ if (th->filled ) {
1580
+ joinArray (f.first , f.thunks , f.val , f.elementId , th->content );
1581
+ f.elementId ++;
1582
+ } else {
1583
+ stack.newCall (f.location , th, th->self , th->offset , th->upValues );
1584
+ return th->body ;
1591
1585
}
1592
- scratch = makeArray (running);
1593
1586
}
1587
+ scratch = makeArray (f.thunks );
1594
1588
return nullptr ;
1595
1589
}
1596
1590
@@ -1608,11 +1602,21 @@ class Interpreter {
1608
1602
}
1609
1603
Frame &f = stack.top ();
1610
1604
if (args[0 ].t == Value::STRING) {
1605
+ f.kind = FRAME_BUILTIN_JOIN_STRINGS;
1606
+ f.val = args[0 ]; // sep
1607
+ f.val2 = args[1 ]; // arr
1611
1608
f.str .clear ();
1612
- return joinStrings (args[0 ], args[1 ], 0 , f.str );
1609
+ f.first = true ;
1610
+ f.elementId = 0 ;
1611
+ return joinStrings ();
1613
1612
} else {
1613
+ f.kind = FRAME_BUILTIN_JOIN_ARRAYS;
1614
+ f.val = args[0 ]; // sep
1615
+ f.val2 = args[1 ]; // arr
1614
1616
f.thunks .clear ();
1615
- return joinArrays (args[0 ], args[1 ], 0 , f.thunks );
1617
+ f.first = true ;
1618
+ f.elementId = 0 ;
1619
+ return joinArrays ();
1616
1620
}
1617
1621
}
1618
1622
@@ -2832,19 +2836,19 @@ class Interpreter {
2832
2836
} break ;
2833
2837
2834
2838
case FRAME_BUILTIN_JOIN_STRINGS: {
2835
- joinString (f.str , f.val , f.elementId , scratch);
2839
+ joinString (f.first , f. str , f.val , f.elementId , scratch);
2836
2840
f.elementId ++;
2837
- auto *ast = joinStrings (f. val , f. val2 , f. elementId , f. str );
2841
+ auto *ast = joinStrings ();
2838
2842
if (ast != nullptr ) {
2839
2843
ast_ = ast;
2840
2844
goto recurse;
2841
2845
}
2842
2846
} break ;
2843
2847
2844
2848
case FRAME_BUILTIN_JOIN_ARRAYS: {
2845
- joinArray (f.thunks , f.val , f.elementId , scratch);
2849
+ joinArray (f.first , f. thunks , f.val , f.elementId , scratch);
2846
2850
f.elementId ++;
2847
- auto *ast = joinArrays (f. val , f. val2 , f. elementId , f. thunks );
2851
+ auto *ast = joinArrays ();
2848
2852
if (ast != nullptr ) {
2849
2853
ast_ = ast;
2850
2854
goto recurse;
0 commit comments