Skip to content

Commit 24adfc4

Browse files
committed
fix: implement slices.Grow
Signed-off-by: Christian Stewart <christian@aperture.us>
1 parent 9b20da0 commit 24adfc4

File tree

6 files changed

+98
-0
lines changed

6 files changed

+98
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Before Grow: len= 3 cap= 3
2+
After Grow: len= 3 cap= 8
3+
slices.Grow test finished

compliance/tests/slices_grow/index.ts

Whitespace-only changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
import "slices"
4+
5+
func main() {
6+
s := []int{1, 2, 3}
7+
println("Before Grow: len=", len(s), "cap=", cap(s))
8+
s = slices.Grow(s, 5)
9+
println("After Grow: len=", len(s), "cap=", cap(s))
10+
println("slices.Grow test finished")
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Generated file based on slices_grow.go
2+
// Updated when compliance tests are re-run, DO NOT EDIT!
3+
4+
import * as $ from "@goscript/builtin/index.js"
5+
6+
import * as slices from "@goscript/slices/index.js"
7+
8+
export async function main(): Promise<void> {
9+
let s = $.arrayToSlice<number>([1, 2, 3])
10+
console.log("Before Grow: len=", $.len(s), "cap=", $.cap(s))
11+
s = slices.Grow(s, 5)
12+
console.log("After Grow: len=", $.len(s), "cap=", $.cap(s))
13+
console.log("slices.Grow test finished")
14+
}
15+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"compilerOptions": {
3+
"allowImportingTsExtensions": true,
4+
"lib": [
5+
"es2022",
6+
"esnext.disposable",
7+
"dom"
8+
],
9+
"module": "nodenext",
10+
"moduleResolution": "nodenext",
11+
"noEmit": true,
12+
"paths": {
13+
"*": [
14+
"./*"
15+
],
16+
"@goscript/*": [
17+
"../../../gs/*",
18+
"../../../compliance/deps/*"
19+
],
20+
"@goscript/github.com/aperturerobotics/goscript/compliance/tests/slices_grow/*": [
21+
"./*"
22+
]
23+
},
24+
"sourceMap": true,
25+
"target": "es2022"
26+
},
27+
"extends": "../../../tsconfig.json",
28+
"include": [
29+
"index.ts",
30+
"slices_grow.gs.ts"
31+
]
32+
}

gs/slices/slices.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,43 @@ export function Delete<T>(s: $.Slice<T>, i: number, j: number): $.Slice<T> {
6262
return $.goSlice(s, 0, length - deleteCount) as $.Slice<T>
6363
}
6464

65+
/**
66+
* Grow increases the slice's capacity, if necessary, to guarantee space for
67+
* another n elements. After Grow(n), at least n elements can be appended
68+
* to the slice without another allocation. If n is negative or too large to
69+
* allocate the memory, Grow panics.
70+
* This is equivalent to Go's slices.Grow function.
71+
* @param s The slice to grow
72+
* @param n The number of additional elements to guarantee space for
73+
* @returns The slice with increased capacity
74+
*/
75+
export function Grow<T>(s: $.Slice<T>, n: number): $.Slice<T> {
76+
if (n < 0) {
77+
throw new Error(`slices.Grow: negative n: ${n}`)
78+
}
79+
const currentLen = $.len(s)
80+
const currentCap = $.cap(s)
81+
const neededCap = currentLen + n
82+
83+
if (neededCap <= currentCap) {
84+
return s
85+
}
86+
87+
// Create new slice with increased capacity
88+
// Go's growth strategy typically doubles capacity when needed
89+
let newCap = currentCap * 2
90+
if (newCap < neededCap) {
91+
newCap = neededCap
92+
}
93+
94+
const newSlice = $.makeSlice<T>(currentLen, newCap)
95+
for (let i = 0; i < currentLen; i++) {
96+
;(newSlice as any)[i] = (s as any)[i]
97+
}
98+
99+
return newSlice
100+
}
101+
65102
/**
66103
* BinarySearchFunc works like BinarySearch, but uses a custom comparison function.
67104
* The slice must be sorted in increasing order, where "increasing" is defined by cmp.

0 commit comments

Comments
 (0)