Skip to content

Commit b7c41a6

Browse files
authored
feat(stdlib)!: Use String length as default end in String.slice function (#1748)
* feat(stdlib)!: Use String length as default end in String.slice function * Regen docs
1 parent 7d3006d commit b7c41a6

File tree

7 files changed

+66
-58
lines changed

7 files changed

+66
-58
lines changed

compiler/test/stdlib/buffer.test.gr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ for (let mut i = 0; i < Array.length(slices); i += 1) {
271271
let (str, start, end) = slices[i]
272272
let buf = Buffer.make(0)
273273
Buffer.addStringSlice(start, end, str, buf)
274-
assert Buffer.toString(buf) == String.slice(start, end, str)
274+
assert Buffer.toString(buf) == String.slice(start, end=end, str)
275275
}
276276

277277
// addBytesSlice

compiler/test/stdlib/string.test.gr

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -129,24 +129,25 @@ assert String.split("🚀 ", emojis) ==
129129
assert String.split(" ", " foo bar baz ") == [> "", "foo", "bar", "baz", ""]
130130

131131
// slice tests
132-
assert String.slice(0, 0, empty) == empty
133-
assert String.slice(0, 1, fox) == "T"
134-
assert String.slice(0, 2, fox) == "Th"
135-
assert String.slice(0, 3, fox) == "The"
136-
assert String.slice(0, 4, fox) == "The "
137-
assert String.slice(0, 5, fox) == "The q"
138-
assert String.slice(35, 39, fox) == "lazy"
139-
assert String.slice(35, 44, fox) == "lazy dog."
140-
assert String.slice(-9, -1, fox) == "lazy dog"
141-
assert String.slice(35, -1, fox) == "lazy dog"
142-
assert String.slice(35, -5, fox) == "lazy"
143-
assert String.slice(0, 44, fox) == fox
144-
assert String.slice(44, 44, fox) == empty
145-
assert String.slice(0, 1, emoji) == emoji
146-
assert String.slice(-2, 1, emoji) == emoji
147-
assert String.slice(-1, -1, emoji) == empty
148-
assert String.slice(0, 1, "💪🏾") == "💪"
149-
assert String.slice(1, 2, "💪🏾") == "🏾"
132+
assert String.slice(0, end=0, empty) == empty
133+
assert String.slice(0, end=1, fox) == "T"
134+
assert String.slice(0, end=2, fox) == "Th"
135+
assert String.slice(0, end=3, fox) == "The"
136+
assert String.slice(0, end=4, fox) == "The "
137+
assert String.slice(0, end=5, fox) == "The q"
138+
assert String.slice(35, end=39, fox) == "lazy"
139+
assert String.slice(35, end=44, fox) == "lazy dog."
140+
assert String.slice(-9, end=-1, fox) == "lazy dog"
141+
assert String.slice(35, end=-1, fox) == "lazy dog"
142+
assert String.slice(35, end=-5, fox) == "lazy"
143+
assert String.slice(0, end=44, fox) == fox
144+
assert String.slice(44, end=44, fox) == empty
145+
assert String.slice(0, end=1, emoji) == emoji
146+
assert String.slice(-2, end=1, emoji) == emoji
147+
assert String.slice(-1, end=-1, emoji) == empty
148+
assert String.slice(0, end=1, "💪🏾") == "💪"
149+
assert String.slice(1, end=2, "💪🏾") == "🏾"
150+
assert String.slice(start=0, fox) == fox
150151

151152
// contains tests
152153
assert String.contains("", short)

stdlib/buffer.gr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ provide let addChar = (char, buffer) => {
335335
*/
336336
@unsafe
337337
provide let addStringSlice = (start: Number, end, string, buffer) => {
338-
let slice = String.slice(start, end, string)
338+
let slice = String.slice(start, end=end, string)
339339

340340
let bytelen = String.byteLength(slice)
341341

stdlib/path.gr

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,15 @@ let lexPath = (pathStr, platform) => {
227227
for (let mut i = 0; i < len; i += 1) {
228228
if (isSeparator(String.charAt(i, pathStr))) {
229229
if (segBeginI != i) {
230-
let tok = makeToken(String.slice(segBeginI, i, pathStr))
230+
let tok = makeToken(String.slice(segBeginI, end=i, pathStr))
231231
revTokens = [tok, ...revTokens]
232232
}
233233
revTokens = [Slash, ...revTokens]
234234
segBeginI = i + 1
235235
}
236236
}
237237
if (segBeginI < len) {
238-
let lastPart = String.slice(segBeginI, len, pathStr)
238+
let lastPart = String.slice(segBeginI, end=len, pathStr)
239239
revTokens = [makeToken(lastPart), ...revTokens]
240240
}
241241
List.reverse(revTokens)
@@ -693,13 +693,12 @@ provide let basename = (path: Path) => {
693693
let stemExtHelper = (path: PathInfo) =>
694694
match (path) {
695695
(_, _, [name, ..._]) => {
696-
let len = String.length(name)
697696
// trim first character (which is possibly a .) off as trick for
698697
// splitting .a.b.c into .a, .b.c
699-
match (String.indexOf(".", String.slice(1, len, name))) {
698+
match (String.indexOf(".", String.slice(1, name))) {
700699
Some(dotI) => {
701700
let dotI = dotI + 1
702-
(String.slice(0, dotI, name), String.slice(dotI, len, name))
701+
(String.slice(0, end=dotI, name), String.slice(dotI, name))
703702
},
704703
None => (name, ""),
705704
}

stdlib/regex.gr

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3529,7 +3529,7 @@ let checkMustString = (ms, buf: MatchBuf, pos, endPos) => {
35293529
) {
35303530
buf.matchInput
35313531
} else {
3532-
String.slice(pos, endPos, buf.matchInput)
3532+
String.slice(pos, end=endPos, buf.matchInput)
35333533
}
35343534
Option.isSome(String.indexOf(ms, toCheck))
35353535
},
@@ -3656,7 +3656,7 @@ let makeMatchResult = (origString, start, end, state) => {
36563656
}
36573657
let getMatchGroup = n => {
36583658
match (getMatchGroupPosition(n)) {
3659-
Some((start, end)) => Some(String.slice(start, end, origString)),
3659+
Some((start, end)) => Some(String.slice(start, end=end, origString)),
36603660
None => None,
36613661
}
36623662
}
@@ -3671,7 +3671,7 @@ let makeMatchResult = (origString, start, end, state) => {
36713671
let getAllMatchGroups = () => {
36723672
Array.map(o => match (o) {
36733673
None => None,
3674-
Some((start, end)) => Some(String.slice(start, end, origString)),
3674+
Some((start, end)) => Some(String.slice(start, end=end, origString)),
36753675
}, getAllMatchGroupPositions())
36763676
}
36773677
{
@@ -3691,7 +3691,7 @@ let fastDriveRegexIsMatch = (rx, string, startOffset, endOffset) => {
36913691
else Array.make(0, None)
36923692
let toWrap =
36933693
if (startOffset == 0 && endOffset == String.length(string)) string
3694-
else String.slice(startOffset, endOffset, string)
3694+
else String.slice(startOffset, end=endOffset, string)
36953695
let buf = makeMatchBuffer(toWrap)
36963696
Option.isSome(
36973697
searchMatch(rx, buf, 0, 0, Array.length(buf.matchInputExploded), state)
@@ -3705,7 +3705,7 @@ let rec fastDriveRegexMatchAll = (rx, string, startOffset, endOffset) => {
37053705
let state = Array.make(rx.reNumGroups, None)
37063706
let toWrap =
37073707
if (startOffset == 0 && endOffset == String.length(string)) string
3708-
else String.slice(startOffset, endOffset, string)
3708+
else String.slice(startOffset, end=endOffset, string)
37093709
let buf = makeMatchBuffer(toWrap)
37103710
match (searchMatch(
37113711
rx,
@@ -3745,7 +3745,7 @@ let fastDriveRegexMatch = (rx, string, startOffset, endOffset) => {
37453745
let state = Array.make(rx.reNumGroups, None)
37463746
let toWrap =
37473747
if (startOffset == 0 && endOffset == String.length(string)) string
3748-
else String.slice(startOffset, endOffset, string)
3748+
else String.slice(startOffset, end=endOffset, string)
37493749
let buf = makeMatchBuffer(toWrap)
37503750
match (searchMatch(
37513751
rx,
@@ -3893,15 +3893,14 @@ let computeReplacement =
38933893
let replacementExploded = String.explode(replacementString)
38943894
let len = Array.length(replacementExploded)
38953895
let mut acc = []
3896-
let getBeforeMatch = () => String.slice(0, start, matchBuf.matchInput)
3897-
let getAfterMatch = () =>
3898-
String.slice(end, String.length(matchBuf.matchInput), matchBuf.matchInput)
3896+
let getBeforeMatch = () => String.slice(0, end=start, matchBuf.matchInput)
3897+
let getAfterMatch = () => String.slice(end, matchBuf.matchInput)
38993898
let getInputSubstr = n => {
39003899
if (n == 0) {
3901-
String.slice(start, end, matchBuf.matchInput)
3900+
String.slice(start, end=end, matchBuf.matchInput)
39023901
} else if (n - 1 < Array.length(state)) {
39033902
match (state[n - 1]) {
3904-
Some((start, end)) => String.slice(start, end, matchBuf.matchInput),
3903+
Some((start, end)) => String.slice(start, end=end, matchBuf.matchInput),
39053904
None => "",
39063905
}
39073906
} else {
@@ -3910,7 +3909,7 @@ let computeReplacement =
39103909
}
39113910
let consRange = (start, end, lst) => {
39123911
if (start == end) lst
3913-
else [String.slice(start, end, replacementString), ...lst]
3912+
else [String.slice(start, end=end, replacementString), ...lst]
39143913
}
39153914
let rec loop = (pos, since) => {
39163915
if (pos == len) {
@@ -3986,7 +3985,7 @@ let regexReplaceHelp =
39863985
""
39873986
} else {
39883987
String.concat(
3989-
String.slice(searchPos, searchPos + 1, toSearch),
3988+
String.slice(searchPos, end=searchPos + 1, toSearch),
39903989
loop(searchPos + 1)
39913990
)
39923991
}
@@ -3996,15 +3995,13 @@ let regexReplaceHelp =
39963995
}
39973996
match (poss) {
39983997
None =>
3999-
if (searchPos == 0) toSearch
4000-
else String.slice(searchPos, String.length(toSearch), toSearch),
3998+
if (searchPos == 0) toSearch else String.slice(searchPos, toSearch),
40013999
Some((start, end)) =>
40024000
String.concat(
4003-
String.slice(searchPos, start, toSearch),
4001+
String.slice(searchPos, end=start, toSearch),
40044002
String.concat(
40054003
computeReplacement(buf, replacement, start, end, state),
4006-
if (all) recur(start, end)
4007-
else String.slice(end, String.length(toSearch), toSearch)
4004+
if (all) recur(start, end) else String.slice(end, toSearch)
40084005
)
40094006
),
40104007
}
@@ -4083,18 +4080,18 @@ let regexSplitHelp = (rx: RegularExpression, str: String, all: Bool) => {
40834080
Some((start, end)) => {
40844081
if (i == 0) {
40854082
// Add the string between this match and the last match
4086-
out = [String.slice(currentLocation, start, str), ...out]
4083+
out = [String.slice(currentLocation, end=start, str), ...out]
40874084
} else {
40884085
// This adds the groups back in
4089-
out = [String.slice(start, end, str), ...out]
4086+
out = [String.slice(start, end=end, str), ...out]
40904087
}
40914088
if (end > currentLocation) currentLocation = end
40924089
},
40934090
None => void,
40944091
}
40954092
}, locations)
40964093
}, regexMatches)
4097-
out = [String.slice(currentLocation, String.length(str), str), ...out]
4094+
out = [String.slice(currentLocation, str), ...out]
40984095
List.reverse(out)
40994096
}
41004097

stdlib/string.gr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ provide let split = (separator: String, string: String) => {
618618
* Get a portion of a string.
619619
*
620620
* @param start: The start position of the substring
621-
* @param to: The end position of the substring, exclusive
621+
* @param end: The end position of the substring, exclusive
622622
* @param string: The input string
623623
* @returns The substring from the initial string
624624
*
@@ -628,12 +628,14 @@ provide let split = (separator: String, string: String) => {
628628
* @throws IndexOutOfBounds: When `end` is out of bounds
629629
* @throws InvalidArgument(String): When `start` is greater than `end`
630630
*
631-
* @example String.slice(0, 5, "Hello world") == "Hello"
631+
* @example String.slice(0, end=5, "Hello world") == "Hello"
632+
* @example String.slice(0, "Hello world") == "Hello world"
632633
*
633634
* @since v0.1.0
635+
* @history v0.6.0: Default `end` to the String length
634636
*/
635637
@unsafe
636-
provide let slice = (start: Number, to: Number, string: String) => {
638+
provide let slice = (start: Number, end=length(string), string: String) => {
637639
from WasmI32 use {
638640
add as (+),
639641
sub as (-),
@@ -645,8 +647,6 @@ provide let slice = (start: Number, to: Number, string: String) => {
645647
eq as (==),
646648
ne as (!=),
647649
}
648-
let startOrig = start
649-
let toOrig = to
650650

651651
let len = WasmI32.fromGrain(length(string)) >> 1n
652652
let size = WasmI32.fromGrain(byteLength(string)) >> 1n
@@ -659,7 +659,7 @@ provide let slice = (start: Number, to: Number, string: String) => {
659659
}
660660
start = start >> 1n
661661

662-
let mut to = WasmI32.fromGrain(to)
662+
let mut to = WasmI32.fromGrain(end)
663663
if ((to & 1n) != 1n) {
664664
throw InvalidArgument("Invalid end index")
665665
}

stdlib/string.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,20 @@ String.split(" ", "Hello world") == [> "Hello", "world"]
419419

420420
### String.**slice**
421421

422-
<details disabled>
423-
<summary tabindex="-1">Added in <code>0.1.0</code></summary>
424-
No other changes yet.
422+
<details>
423+
<summary>Added in <code>0.1.0</code></summary>
424+
<table>
425+
<thead>
426+
<tr><th>version</th><th>changes</th></tr>
427+
</thead>
428+
<tbody>
429+
<tr><td><code>next</code></td><td>Default `end` to the String length</td></tr>
430+
</tbody>
431+
</table>
425432
</details>
426433

427434
```grain
428-
slice : (start: Number, to: Number, string: String) -> String
435+
slice : (start: Number, ?end: Number, string: String) -> String
429436
```
430437

431438
Get a portion of a string.
@@ -435,7 +442,7 @@ Parameters:
435442
|param|type|description|
436443
|-----|----|-----------|
437444
|`start`|`Number`|The start position of the substring|
438-
|`to`|`Number`|The end position of the substring, exclusive|
445+
|`end`|`Option<Number>`|The end position of the substring, exclusive|
439446
|`string`|`String`|The input string|
440447

441448
Returns:
@@ -460,7 +467,11 @@ Throws:
460467
Examples:
461468

462469
```grain
463-
String.slice(0, 5, "Hello world") == "Hello"
470+
String.slice(0, end=5, "Hello world") == "Hello"
471+
```
472+
473+
```grain
474+
String.slice(0, "Hello world") == "Hello world"
464475
```
465476

466477
### String.**contains**

0 commit comments

Comments
 (0)