182 lines
3.5 KiB
Forth
182 lines
3.5 KiB
Forth
scenario array-from-args [
|
|
run [
|
|
local-scope
|
|
x:&:@:num <- new-array 0, 1, 2
|
|
10:@:num/raw <- copy *x
|
|
]
|
|
memory-should-contain [
|
|
10 <- 3 # array length
|
|
11 <- 0
|
|
12 <- 1
|
|
13 <- 2
|
|
]
|
|
]
|
|
|
|
# create an array out of a list of args
|
|
def new-array -> result:&:@:_elem [
|
|
local-scope
|
|
capacity:num <- copy 0
|
|
{
|
|
# while read curr-value
|
|
curr-value:_elem, exists?:bool <- next-input
|
|
break-unless exists?
|
|
capacity <- add capacity, 1
|
|
loop
|
|
}
|
|
result <- new _elem:type, capacity
|
|
rewind-inputs
|
|
i:num <- copy 0
|
|
{
|
|
# while read curr-value
|
|
done?:bool <- greater-or-equal i, capacity
|
|
break-if done?
|
|
curr-value:_elem, exists?:bool <- next-input
|
|
assert exists?, [error in rewinding inputs to new-array]
|
|
*result <- put-index *result, i, curr-value
|
|
i <- add i, 1
|
|
loop
|
|
}
|
|
return result
|
|
]
|
|
|
|
# fill an existing array with a set of numbers
|
|
# (contributed by Caleb Couch)
|
|
def fill array:&:@:num -> array:&:@:num [
|
|
local-scope
|
|
load-inputs
|
|
loopn:num <- copy 0
|
|
length:num <- length *array
|
|
{
|
|
length?:bool <- equal loopn, length
|
|
break-if length?
|
|
object:num, arg-received?:bool <- next-input
|
|
break-unless arg-received?
|
|
*array <- put-index *array, loopn, object
|
|
loopn <- add loopn, 1
|
|
loop
|
|
}
|
|
]
|
|
|
|
scenario fill-on-an-empty-array [
|
|
local-scope
|
|
array:&:@:num <- new number:type, 3
|
|
run [
|
|
array <- fill array, 1 2 3
|
|
10:@:num/raw <- copy *array
|
|
]
|
|
memory-should-contain [
|
|
10 <- 3
|
|
11 <- 1
|
|
12 <- 2
|
|
13 <- 3
|
|
]
|
|
]
|
|
|
|
scenario fill-overwrites-existing-values [
|
|
local-scope
|
|
array:&:@:num <- new number:type, 3
|
|
*array <- put-index *array, 0, 4
|
|
run [
|
|
array <- fill array, 1 2 3
|
|
10:@:num/raw <- copy *array
|
|
]
|
|
memory-should-contain [
|
|
10 <- 3
|
|
11 <- 1
|
|
12 <- 2
|
|
13 <- 3
|
|
]
|
|
]
|
|
|
|
scenario fill-exits-gracefully-when-given-no-inputs [
|
|
local-scope
|
|
array:&:@:num <- new number:type, 3
|
|
run [
|
|
array <- fill array
|
|
10:@:num/raw <- copy *array
|
|
]
|
|
memory-should-contain [
|
|
10 <- 3
|
|
11 <- 0
|
|
12 <- 0
|
|
13 <- 0
|
|
]
|
|
]
|
|
|
|
# swap two elements of an array
|
|
# (contributed by Caleb Couch)
|
|
def swap array:&:@:num, index1:num, index2:num -> array:&:@:num [
|
|
local-scope
|
|
load-inputs
|
|
object1:num <- index *array, index1
|
|
object2:num <- index *array, index2
|
|
*array <- put-index *array, index1, object2
|
|
*array <- put-index *array, index2, object1
|
|
]
|
|
|
|
scenario swap-works [
|
|
local-scope
|
|
array:&:@:num <- new number:type, 4
|
|
array <- fill array, 4 3 2 1
|
|
run [
|
|
array <- swap array, 0, 2
|
|
10:num/raw <- index *array, 0
|
|
11:num/raw <- index *array, 2
|
|
]
|
|
memory-should-contain [
|
|
10 <- 2
|
|
11 <- 4
|
|
]
|
|
]
|
|
|
|
# reverse the elements of an array
|
|
# (contributed by Caleb Couch)
|
|
def reverse array:&:@:_elem -> array:&:@:_elem [
|
|
local-scope
|
|
load-inputs
|
|
start:num <- copy 0
|
|
length:num <- length *array
|
|
end:num <- subtract length, 1
|
|
{
|
|
done?:bool <- greater-or-equal start, end
|
|
break-if done?
|
|
array <- swap array, start, end
|
|
start <- add start, 1
|
|
end <- subtract end, 1
|
|
loop
|
|
}
|
|
]
|
|
|
|
scenario reverse-array-odd-length [
|
|
local-scope
|
|
array:&:@:num <- new number:type, 3
|
|
array <- fill array, 3 2 1
|
|
run [
|
|
array <- reverse array
|
|
10:@:num/raw <- copy *array
|
|
]
|
|
memory-should-contain [
|
|
10 <- 3
|
|
11 <- 1
|
|
12 <- 2
|
|
13 <- 3
|
|
]
|
|
]
|
|
|
|
scenario reverse-array-even-length [
|
|
local-scope
|
|
array:&:@:num <- new number:type, 4
|
|
array <- fill array, 4 3 2 1
|
|
run [
|
|
array <- reverse array
|
|
10:@:num/raw <- copy *array
|
|
]
|
|
memory-should-contain [
|
|
10 <- 4
|
|
11 <- 1
|
|
12 <- 2
|
|
13 <- 3
|
|
14 <- 4
|
|
]
|
|
]
|