Skip to content

Commit

Permalink
feat(stdlib)!: Use String length as default end in String.slice fun…
Browse files Browse the repository at this point in the history
…ction (grain-lang#1748)

* feat(stdlib)!: Use String length as default end in String.slice function

* Regen docs
  • Loading branch information
phated authored Mar 16, 2023
1 parent 7d3006d commit b7c41a6
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 58 deletions.
2 changes: 1 addition & 1 deletion compiler/test/stdlib/buffer.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ for (let mut i = 0; i < Array.length(slices); i += 1) {
let (str, start, end) = slices[i]
let buf = Buffer.make(0)
Buffer.addStringSlice(start, end, str, buf)
assert Buffer.toString(buf) == String.slice(start, end, str)
assert Buffer.toString(buf) == String.slice(start, end=end, str)
}

// addBytesSlice
Expand Down
37 changes: 19 additions & 18 deletions compiler/test/stdlib/string.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -129,24 +129,25 @@ assert String.split("🚀 ", emojis) ==
assert String.split(" ", " foo bar baz ") == [> "", "foo", "bar", "baz", ""]

// slice tests
assert String.slice(0, 0, empty) == empty
assert String.slice(0, 1, fox) == "T"
assert String.slice(0, 2, fox) == "Th"
assert String.slice(0, 3, fox) == "The"
assert String.slice(0, 4, fox) == "The "
assert String.slice(0, 5, fox) == "The q"
assert String.slice(35, 39, fox) == "lazy"
assert String.slice(35, 44, fox) == "lazy dog."
assert String.slice(-9, -1, fox) == "lazy dog"
assert String.slice(35, -1, fox) == "lazy dog"
assert String.slice(35, -5, fox) == "lazy"
assert String.slice(0, 44, fox) == fox
assert String.slice(44, 44, fox) == empty
assert String.slice(0, 1, emoji) == emoji
assert String.slice(-2, 1, emoji) == emoji
assert String.slice(-1, -1, emoji) == empty
assert String.slice(0, 1, "💪🏾") == "💪"
assert String.slice(1, 2, "💪🏾") == "🏾"
assert String.slice(0, end=0, empty) == empty
assert String.slice(0, end=1, fox) == "T"
assert String.slice(0, end=2, fox) == "Th"
assert String.slice(0, end=3, fox) == "The"
assert String.slice(0, end=4, fox) == "The "
assert String.slice(0, end=5, fox) == "The q"
assert String.slice(35, end=39, fox) == "lazy"
assert String.slice(35, end=44, fox) == "lazy dog."
assert String.slice(-9, end=-1, fox) == "lazy dog"
assert String.slice(35, end=-1, fox) == "lazy dog"
assert String.slice(35, end=-5, fox) == "lazy"
assert String.slice(0, end=44, fox) == fox
assert String.slice(44, end=44, fox) == empty
assert String.slice(0, end=1, emoji) == emoji
assert String.slice(-2, end=1, emoji) == emoji
assert String.slice(-1, end=-1, emoji) == empty
assert String.slice(0, end=1, "💪🏾") == "💪"
assert String.slice(1, end=2, "💪🏾") == "🏾"
assert String.slice(start=0, fox) == fox

// contains tests
assert String.contains("", short)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/buffer.gr
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ provide let addChar = (char, buffer) => {
*/
@unsafe
provide let addStringSlice = (start: Number, end, string, buffer) => {
let slice = String.slice(start, end, string)
let slice = String.slice(start, end=end, string)

let bytelen = String.byteLength(slice)

Expand Down
9 changes: 4 additions & 5 deletions stdlib/path.gr
Original file line number Diff line number Diff line change
Expand Up @@ -227,15 +227,15 @@ let lexPath = (pathStr, platform) => {
for (let mut i = 0; i < len; i += 1) {
if (isSeparator(String.charAt(i, pathStr))) {
if (segBeginI != i) {
let tok = makeToken(String.slice(segBeginI, i, pathStr))
let tok = makeToken(String.slice(segBeginI, end=i, pathStr))
revTokens = [tok, ...revTokens]
}
revTokens = [Slash, ...revTokens]
segBeginI = i + 1
}
}
if (segBeginI < len) {
let lastPart = String.slice(segBeginI, len, pathStr)
let lastPart = String.slice(segBeginI, end=len, pathStr)
revTokens = [makeToken(lastPart), ...revTokens]
}
List.reverse(revTokens)
Expand Down Expand Up @@ -693,13 +693,12 @@ provide let basename = (path: Path) => {
let stemExtHelper = (path: PathInfo) =>
match (path) {
(_, _, [name, ..._]) => {
let len = String.length(name)
// trim first character (which is possibly a .) off as trick for
// splitting .a.b.c into .a, .b.c
match (String.indexOf(".", String.slice(1, len, name))) {
match (String.indexOf(".", String.slice(1, name))) {
Some(dotI) => {
let dotI = dotI + 1
(String.slice(0, dotI, name), String.slice(dotI, len, name))
(String.slice(0, end=dotI, name), String.slice(dotI, name))
},
None => (name, ""),
}
Expand Down
39 changes: 18 additions & 21 deletions stdlib/regex.gr
Original file line number Diff line number Diff line change
Expand Up @@ -3529,7 +3529,7 @@ let checkMustString = (ms, buf: MatchBuf, pos, endPos) => {
) {
buf.matchInput
} else {
String.slice(pos, endPos, buf.matchInput)
String.slice(pos, end=endPos, buf.matchInput)
}
Option.isSome(String.indexOf(ms, toCheck))
},
Expand Down Expand Up @@ -3656,7 +3656,7 @@ let makeMatchResult = (origString, start, end, state) => {
}
let getMatchGroup = n => {
match (getMatchGroupPosition(n)) {
Some((start, end)) => Some(String.slice(start, end, origString)),
Some((start, end)) => Some(String.slice(start, end=end, origString)),
None => None,
}
}
Expand All @@ -3671,7 +3671,7 @@ let makeMatchResult = (origString, start, end, state) => {
let getAllMatchGroups = () => {
Array.map(o => match (o) {
None => None,
Some((start, end)) => Some(String.slice(start, end, origString)),
Some((start, end)) => Some(String.slice(start, end=end, origString)),
}, getAllMatchGroupPositions())
}
{
Expand All @@ -3691,7 +3691,7 @@ let fastDriveRegexIsMatch = (rx, string, startOffset, endOffset) => {
else Array.make(0, None)
let toWrap =
if (startOffset == 0 && endOffset == String.length(string)) string
else String.slice(startOffset, endOffset, string)
else String.slice(startOffset, end=endOffset, string)
let buf = makeMatchBuffer(toWrap)
Option.isSome(
searchMatch(rx, buf, 0, 0, Array.length(buf.matchInputExploded), state)
Expand All @@ -3705,7 +3705,7 @@ let rec fastDriveRegexMatchAll = (rx, string, startOffset, endOffset) => {
let state = Array.make(rx.reNumGroups, None)
let toWrap =
if (startOffset == 0 && endOffset == String.length(string)) string
else String.slice(startOffset, endOffset, string)
else String.slice(startOffset, end=endOffset, string)
let buf = makeMatchBuffer(toWrap)
match (searchMatch(
rx,
Expand Down Expand Up @@ -3745,7 +3745,7 @@ let fastDriveRegexMatch = (rx, string, startOffset, endOffset) => {
let state = Array.make(rx.reNumGroups, None)
let toWrap =
if (startOffset == 0 && endOffset == String.length(string)) string
else String.slice(startOffset, endOffset, string)
else String.slice(startOffset, end=endOffset, string)
let buf = makeMatchBuffer(toWrap)
match (searchMatch(
rx,
Expand Down Expand Up @@ -3893,15 +3893,14 @@ let computeReplacement =
let replacementExploded = String.explode(replacementString)
let len = Array.length(replacementExploded)
let mut acc = []
let getBeforeMatch = () => String.slice(0, start, matchBuf.matchInput)
let getAfterMatch = () =>
String.slice(end, String.length(matchBuf.matchInput), matchBuf.matchInput)
let getBeforeMatch = () => String.slice(0, end=start, matchBuf.matchInput)
let getAfterMatch = () => String.slice(end, matchBuf.matchInput)
let getInputSubstr = n => {
if (n == 0) {
String.slice(start, end, matchBuf.matchInput)
String.slice(start, end=end, matchBuf.matchInput)
} else if (n - 1 < Array.length(state)) {
match (state[n - 1]) {
Some((start, end)) => String.slice(start, end, matchBuf.matchInput),
Some((start, end)) => String.slice(start, end=end, matchBuf.matchInput),
None => "",
}
} else {
Expand All @@ -3910,7 +3909,7 @@ let computeReplacement =
}
let consRange = (start, end, lst) => {
if (start == end) lst
else [String.slice(start, end, replacementString), ...lst]
else [String.slice(start, end=end, replacementString), ...lst]
}
let rec loop = (pos, since) => {
if (pos == len) {
Expand Down Expand Up @@ -3986,7 +3985,7 @@ let regexReplaceHelp =
""
} else {
String.concat(
String.slice(searchPos, searchPos + 1, toSearch),
String.slice(searchPos, end=searchPos + 1, toSearch),
loop(searchPos + 1)
)
}
Expand All @@ -3996,15 +3995,13 @@ let regexReplaceHelp =
}
match (poss) {
None =>
if (searchPos == 0) toSearch
else String.slice(searchPos, String.length(toSearch), toSearch),
if (searchPos == 0) toSearch else String.slice(searchPos, toSearch),
Some((start, end)) =>
String.concat(
String.slice(searchPos, start, toSearch),
String.slice(searchPos, end=start, toSearch),
String.concat(
computeReplacement(buf, replacement, start, end, state),
if (all) recur(start, end)
else String.slice(end, String.length(toSearch), toSearch)
if (all) recur(start, end) else String.slice(end, toSearch)
)
),
}
Expand Down Expand Up @@ -4083,18 +4080,18 @@ let regexSplitHelp = (rx: RegularExpression, str: String, all: Bool) => {
Some((start, end)) => {
if (i == 0) {
// Add the string between this match and the last match
out = [String.slice(currentLocation, start, str), ...out]
out = [String.slice(currentLocation, end=start, str), ...out]
} else {
// This adds the groups back in
out = [String.slice(start, end, str), ...out]
out = [String.slice(start, end=end, str), ...out]
}
if (end > currentLocation) currentLocation = end
},
None => void,
}
}, locations)
}, regexMatches)
out = [String.slice(currentLocation, String.length(str), str), ...out]
out = [String.slice(currentLocation, str), ...out]
List.reverse(out)
}

Expand Down
12 changes: 6 additions & 6 deletions stdlib/string.gr
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ provide let split = (separator: String, string: String) => {
* Get a portion of a string.
*
* @param start: The start position of the substring
* @param to: The end position of the substring, exclusive
* @param end: The end position of the substring, exclusive
* @param string: The input string
* @returns The substring from the initial string
*
Expand All @@ -628,12 +628,14 @@ provide let split = (separator: String, string: String) => {
* @throws IndexOutOfBounds: When `end` is out of bounds
* @throws InvalidArgument(String): When `start` is greater than `end`
*
* @example String.slice(0, 5, "Hello world") == "Hello"
* @example String.slice(0, end=5, "Hello world") == "Hello"
* @example String.slice(0, "Hello world") == "Hello world"
*
* @since v0.1.0
* @history v0.6.0: Default `end` to the String length
*/
@unsafe
provide let slice = (start: Number, to: Number, string: String) => {
provide let slice = (start: Number, end=length(string), string: String) => {
from WasmI32 use {
add as (+),
sub as (-),
Expand All @@ -645,8 +647,6 @@ provide let slice = (start: Number, to: Number, string: String) => {
eq as (==),
ne as (!=),
}
let startOrig = start
let toOrig = to

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

let mut to = WasmI32.fromGrain(to)
let mut to = WasmI32.fromGrain(end)
if ((to & 1n) != 1n) {
throw InvalidArgument("Invalid end index")
}
Expand Down
23 changes: 17 additions & 6 deletions stdlib/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,13 +419,20 @@ String.split(" ", "Hello world") == [> "Hello", "world"]

### String.**slice**

<details disabled>
<summary tabindex="-1">Added in <code>0.1.0</code></summary>
No other changes yet.
<details>
<summary>Added in <code>0.1.0</code></summary>
<table>
<thead>
<tr><th>version</th><th>changes</th></tr>
</thead>
<tbody>
<tr><td><code>next</code></td><td>Default `end` to the String length</td></tr>
</tbody>
</table>
</details>

```grain
slice : (start: Number, to: Number, string: String) -> String
slice : (start: Number, ?end: Number, string: String) -> String
```

Get a portion of a string.
Expand All @@ -435,7 +442,7 @@ Parameters:
|param|type|description|
|-----|----|-----------|
|`start`|`Number`|The start position of the substring|
|`to`|`Number`|The end position of the substring, exclusive|
|`end`|`Option<Number>`|The end position of the substring, exclusive|
|`string`|`String`|The input string|

Returns:
Expand All @@ -460,7 +467,11 @@ Throws:
Examples:

```grain
String.slice(0, 5, "Hello world") == "Hello"
String.slice(0, end=5, "Hello world") == "Hello"
```

```grain
String.slice(0, "Hello world") == "Hello world"
```

### String.**contains**
Expand Down

0 comments on commit b7c41a6

Please sign in to comment.