Skip to content

Commit 6c33d08

Browse files
feat(stdlib): Add String.repeat to String module (#2140)
Co-authored-by: Oscar Spencer <oscar.spen@gmail.com>
1 parent b0fb040 commit 6c33d08

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

compiler/test/stdlib/string.test.gr

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,3 +551,11 @@ assert String.toAsciiLowercase("aBc🌾12Y") == "abc🌾12y"
551551

552552
// toAsciiUppercase
553553
assert String.toAsciiUppercase("aBc🌾12Y") == "ABC🌾12Y"
554+
555+
// String.repeat
556+
assert String.repeat(1, "=.") == "=."
557+
assert String.repeat(10, "=") == "=========="
558+
assert String.repeat(10, "=.") == "=.=.=.=.=.=.=.=.=.=."
559+
assert String.repeat(0, "=.") == ""
560+
assert String.repeat(0, "") == ""
561+
assert String.repeat(5, "") == ""

stdlib/string.gr

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,3 +2328,40 @@ provide let toAsciiUppercase = string => {
23282328
}
23292329
implode(chars)
23302330
}
2331+
2332+
/**
2333+
* Produces a new string by repeating a substring a given number of times.
2334+
*
2335+
* @param count: The number of times to repeat the string
2336+
* @param string: The string to repeat
2337+
* @returns A string containing the repeated input string
2338+
*
2339+
* @throws InvalidArgument(String): When the `count` is not an integer
2340+
* @throws InvalidArgument(String): When the `count` is negative
2341+
*
2342+
* @example assert String.repeat(5, "=") == "====="
2343+
* @example assert String.repeat(0, ".") == ""
2344+
*
2345+
* @since v0.6.7
2346+
*/
2347+
@unsafe
2348+
provide let repeat = (count, string: String) => {
2349+
use WasmI32.{ (+), (*), (<), (&), (!=) }
2350+
if ((WasmI32.fromGrain(count) & 1n) != 1n) {
2351+
throw InvalidArgument("Invalid count value")
2352+
}
2353+
let rawCount = untagSimpleNumber(count)
2354+
if (rawCount < 0n) {
2355+
throw InvalidArgument("Invalid count must be a positive integer or zero")
2356+
}
2357+
let stringPtr = WasmI32.fromGrain(string)
2358+
let byteLength = WasmI32.load(stringPtr, 4n)
2359+
let stringPtr = stringPtr + 8n
2360+
let newStringPtr = allocateString(byteLength * rawCount)
2361+
let strContentPtr = newStringPtr + 8n
2362+
for (let mut i = 0n; i < rawCount; i += 1n) {
2363+
Memory.copy(strContentPtr + byteLength * i, stringPtr, byteLength)
2364+
}
2365+
ignore(string)
2366+
return WasmI32.toGrain(newStringPtr): String
2367+
}

stdlib/string.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,3 +1174,46 @@ Examples:
11741174
assert String.toAsciiUppercase("aBc123") == "ABC123"
11751175
```
11761176

1177+
### String.**repeat**
1178+
1179+
<details disabled>
1180+
<summary tabindex="-1">Added in <code>next</code></summary>
1181+
No other changes yet.
1182+
</details>
1183+
1184+
```grain
1185+
repeat : (count: Number, string: String) => String
1186+
```
1187+
1188+
Produces a new string by repeating a substring a given number of times.
1189+
1190+
Parameters:
1191+
1192+
|param|type|description|
1193+
|-----|----|-----------|
1194+
|`count`|`Number`|The number of times to repeat the string|
1195+
|`string`|`String`|The string to repeat|
1196+
1197+
Returns:
1198+
1199+
|type|description|
1200+
|----|-----------|
1201+
|`String`|A string containing the repeated input string|
1202+
1203+
Throws:
1204+
1205+
`InvalidArgument(String)`
1206+
1207+
* When the `count` is not an integer
1208+
* When the `count` is negative
1209+
1210+
Examples:
1211+
1212+
```grain
1213+
assert String.repeat(5, "=") == "====="
1214+
```
1215+
1216+
```grain
1217+
assert String.repeat(0, ".") == ""
1218+
```
1219+

0 commit comments

Comments
 (0)