Files
l2/stdlib/arr.sl

239 lines
4.7 KiB
Plaintext
Raw Normal View History

2026-01-08 18:34:34 +01:00
# Dynamic arrays (qword elements)
#
# Layout at address `arr`:
# [arr + 0] len (qword)
# [arr + 8] cap (qword)
# [arr + 16] data (qword) = arr + 24
# [arr + 24] elements (cap * 8 bytes)
#
# Allocation: mmap; free: munmap.
# Growth: allocate new block, copy elements, munmap old block.
2026-02-03 09:41:11 +01:00
import mem.sl
#arr_to_dyn [* | std_arr] -> [* | dyn_arr]
word arr_to_dyn
2026-02-10 17:47:59 +01:00
dup @ dup dup 2 * 3 + alloc dup rot !
dup rot 2 * swap 8 + swap ! dup 16 +
dup 8 + dup -rot ! 0 swap 3 pick dup @
8 * swap 8 + swap memcpy 2drop drop nip
end
#arr_new [* | cap] -> [* | arr]
2026-02-03 09:41:11 +01:00
# Create a new array with given initial capacity (minimum 1)
word arr_new
dup 1 < if drop 1 end
dup 8 * 24 + alloc
dup 0 ! # len = 0
over over 8 + swap ! # cap = requested cap
dup 24 + over 16 + swap ! # data = arr + 24
nip
end
2026-01-08 18:34:34 +01:00
#arr_len [* | arr] -> [* | len]
2026-02-03 09:41:11 +01:00
word arr_len @ end
2026-01-08 18:34:34 +01:00
#arr_cap [* | arr] -> [* | cap]
2026-02-03 09:41:11 +01:00
word arr_cap 8 + @ end
2026-01-08 18:34:34 +01:00
#arr_data [* | arr] -> [* | ptr]
2026-02-03 09:41:11 +01:00
word arr_data 16 + @ end
2026-01-08 18:34:34 +01:00
#arr_free [* | arr] -> [*]
2026-02-03 09:41:11 +01:00
word arr_free
dup arr_cap 8 * 24 + free
end
2026-02-18 13:58:08 +01:00
# Helper: copy n qwords from src to dst
#arr_copy_elements [*, dst, src | n] -> [*]
2026-02-03 09:41:11 +01:00
word arr_copy_elements
while dup 0 > do
over @ 3 pick swap ! # dst = *src
swap 8 + swap # src += 8
rot 8 + -rot # dst += 8
1 -
end
drop 2drop
end
2026-01-08 18:34:34 +01:00
#arr_reserve [*, cap | arr] -> [* | arr]
2026-01-08 18:34:34 +01:00
# Ensures capacity >= cap; returns (possibly moved) arr pointer.
2026-02-03 09:41:11 +01:00
word arr_reserve
swap dup 1 < if drop 1 end swap # reqcap arr
# Check: if arr_cap >= reqcap, do nothing
over over arr_cap swap
>= if
nip
else
# Allocate new block
over 8 * 24 + alloc
# Copy header
over arr_len over swap ! # len
2 pick over 8 + swap ! # cap = reqcap
dup 24 + over 16 + swap ! # data = newarr + 24
# Copy elements
dup arr_data
2 pick arr_data
3 pick arr_len
arr_copy_elements
# Free old and return new
swap arr_free
nip
end
end
2026-01-08 18:34:34 +01:00
#arr_push [*, x | arr] -> [* | arr]
2026-02-03 09:41:11 +01:00
# Push element onto array, growing if needed
word arr_push
dup arr_len over arr_cap >= if
dup arr_cap dup 1 < if drop 1 end 2 *
over arr_reserve
nip
end
# Store x at data[len]
dup arr_data over arr_len 8 * +
rot over swap ! drop
# Increment len
dup @ 1 + over swap !
end
2026-01-08 18:34:34 +01:00
#arr_pop [* | arr] -> [*, arr | x]
2026-02-03 09:41:11 +01:00
# Pop element from array (returns 0 if empty)
word arr_pop
dup arr_len 0 == if
0
2026-02-03 09:41:11 +01:00
else
# Decrement len
dup @ 1 - over swap !
# Get element at new len position
dup arr_data over arr_len 8 * + @
end
end
#arr_get [*, i | arr] -> [* | x]
2026-02-03 09:41:11 +01:00
# Get element at index i
word arr_get
arr_data swap 8 * + @
end
#arr_set [*, x, i | arr] -> [*]
2026-02-03 09:41:11 +01:00
# Set element at index i to x
word arr_set
arr_data swap 8 * + swap !
2026-02-10 17:47:59 +01:00
end
2026-02-18 16:05:48 +01:00
#dyn_arr_clone [* | dyn_arr] -> [* | dyn_arr_copy]
word dyn_arr_clone
dup arr_len
dup arr_new
dup arr_data
3 pick arr_data
3 pick
arr_copy_elements
dup >r
swap !
drop
r>
end
#arr_item_ptr [*, i | arr] -> [* | ptr]
word arr_item_ptr
swap 8 * swap 8 + +
end
#arr_get [*, i | arr] -> [* | x]
# Get element from built-in static array
word arr_get_static
arr_item_ptr @
end
#arr_set [*, x, i | arr] -> [*]
# Set element in built-in static array
word arr_set_static
arr_item_ptr swap !
end
#arr_sort [* | arr] -> [* | arr]
# Sort built-in static array in-place in ascending order
word arr_sort
dup >r
dup arr_to_dyn
dyn_arr_sort
dup arr_data
r@ 8 +
swap
r@ @
arr_copy_elements
arr_free
rdrop
end
#dyn_arr_sort [* | dyn_arr] -> [* | dyn_arr]
:asm dyn_arr_sort {
mov rbx, [r12] ; arr
mov rcx, [rbx] ; len
cmp rcx, 1
jle .done
dec rcx ; outer = len - 1
.outer:
xor rdx, rdx ; j = 0
.inner:
cmp rdx, rcx
jge .next_outer
mov r8, [rbx + 16] ; data ptr
lea r9, [r8 + rdx*8] ; &data[j]
mov r10, [r9] ; a = data[j]
mov r11, [r9 + 8] ; b = data[j+1]
cmp r10, r11
jle .no_swap
mov [r9], r11
mov [r9 + 8], r10
.no_swap:
inc rdx
jmp .inner
.next_outer:
dec rcx
jnz .outer
.done:
ret
}
;
#arr_clone [* | arr] -> [* | arr_copy]
# Clone built-in static array (len header + payload)
word arr_clone
dup @ 1 +
dup 8 * alloc
dup >r
rot rot
arr_copy_elements
r>
end
#arr_sorted [* | arr] -> [* | arr_sorted]
word arr_sorted
arr_clone
arr_sort
end
#dyn_arr_sorted [* | dyn_arr] -> [* | dyn_arr_sorted]
word dyn_arr_sorted
dyn_arr_clone
dyn_arr_sort
end