mu/512array.mu

122 lines
3.8 KiB
Forth

# Inserting and deleting in arrays.
#
# The primitives here just do the work of making space and compacting.
fn slide-up _a: (addr array int), start: int, end: int, target: int {
var a/esi: (addr array int) <- copy _a
var src-idx/ecx: int <- copy start
var dest-idx/edx: int <- copy target
# if start == target, nothing to do
{
compare src-idx, dest-idx
break-if-!=
return
}
# if start < target, abort
{
compare src-idx, dest-idx
break-if->
abort "slide-up: target > start; use slide-down instead"
}
# perform the copy
{
compare src-idx, end
break-if->=
var dest/ebx: (addr int) <- index a, dest-idx
var src/eax: (addr int) <- index a, src-idx
var val/eax: int <- copy *src
copy-to *dest, val
src-idx <- increment
dest-idx <- increment
loop
}
}
fn slide-down _a: (addr array int), start: int, end: int, target: int {
var a/esi: (addr array int) <- copy _a
var src-idx/ecx: int <- copy end
src-idx <- decrement
var dest-idx/edx: int <- copy target
dest-idx <- add end
dest-idx <- subtract start
dest-idx <- decrement
# if start == target, nothing to do
{
compare src-idx, dest-idx
break-if-!=
return
}
# if start > target, abort
{
compare src-idx, dest-idx
break-if-<
abort "slide-down: target < start; use slide-down instead"
}
# perform the copy
{
compare src-idx, start
break-if-<
var dest/ebx: (addr int) <- index a, dest-idx
var src/eax: (addr int) <- index a, src-idx
var val/eax: int <- copy *src
copy-to *dest, val
src-idx <- decrement
dest-idx <- decrement
loop
}
}
fn test-slide-up {
check-slide-up "0 1 2 3 0", 1/start 1/end, 0/target, "0 1 2 3 0", "F - test-slide-up/empty-interval"
check-slide-up "0 1 2 3 0", 1/start 2/end, 0/target, "1 1 2 3 0", "F - test-slide-up/single-non-overlapping"
check-slide-up "0 0 0 1 2 3 0", 3/start 6/end, 0/target, "1 2 3 1 2 3 0", "F - test-slide-up/multiple-non-overlapping"
check-slide-up "0 1 2 3 0", 1/start 4/end, 0/target, "1 2 3 3 0", "F - test-slide-up/overlapping"
}
fn test-slide-down {
check-slide-down "0 1 2 3 0", 1/start 1/end, 4/target, "0 1 2 3 0", "F - test-slide-down/empty-interval"
check-slide-down "0 1 2 3 0", 1/start 2/end, 4/target, "0 1 2 3 1", "F - test-slide-down/single-non-overlapping"
check-slide-down "0 1 2 3 0 0 0", 1/start 4/end, 4/target, "0 1 2 3 1 2 3", "F - test-slide-down/multiple-non-overlapping"
check-slide-down "0 1 2 3 0", 1/start 4/end, 2/target, "0 1 1 2 3", "F - test-slide-down/overlapping"
}
# Return the index that val is at.
# If not found, return len-1.
# That way the result is always a valid index to pass into slide-down.
fn find-slide-down-slot-in-array _a: (addr array int), _val: int -> _/ecx: int {
var a/esi: (addr array int) <- copy _a
var val/ebx: int <- copy _val
var max/edx: int <- length a
max <- decrement
var i/ecx: int <- copy 0
{
compare i, max
break-if->=
var curr/eax: (addr int) <- index a, i
compare *curr, val
break-if-=
i <- increment
loop
}
return i
}
# helpers for tests
fn check-slide-up before: (addr array byte), start: int, end: int, target: int, after: (addr array byte), msg: (addr array byte) {
var arr-h: (handle array int)
var arr-ah/eax: (addr handle array int) <- address arr-h
parse-array-of-decimal-ints before, arr-ah
var arr/eax: (addr array int) <- lookup *arr-ah
slide-up arr, start, end, target
check-array-equal arr, after, msg
}
fn check-slide-down before: (addr array byte), start: int, end: int, target: int, after: (addr array byte), msg: (addr array byte) {
var arr-h: (handle array int)
var arr-ah/eax: (addr handle array int) <- address arr-h
parse-array-of-decimal-ints before, arr-ah
var arr/eax: (addr array int) <- lookup *arr-ah
slide-down arr, start, end, target
check-array-equal arr, after, msg
}