Skip to content

Commit 3ba2e7d

Browse files
committed
update readme, add missing rbtree utilities
1 parent 9c5eb5e commit 3ba2e7d

File tree

3 files changed

+186
-10
lines changed

3 files changed

+186
-10
lines changed

README.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The heap is split in 2 pieces: A stack, used to store local variables, and a hea
2828
The heap stack helps storing temporary values. Usually, the native stack will suffice, but it has a few disadvantages:
2929

3030
- It can only peek values below the stack pointer.
31-
- It can't rearrange values.
31+
- It can't rearrange values except for the top 2 (`swap`).
3232
- It's the only way of performing any operation (i.e. there are no registers).
3333
- This makes the offset for peeking also not stable.
3434

@@ -96,6 +96,8 @@ It's based on [Burghard's WSA](https://github.com/wspace/burghard-wsa) as assemb
9696
- `inc` renamed to `readc`.
9797
- `inn` renamed to `readn`.
9898

99+
The compiler also performs tree shaking: it won't include unreachable parts of the code (unused labels).
100+
99101
## Extensions
100102

101103
While on debug mode, this interpreter adds some language extensions to debug or increase performance. For this, a few more operations are added, both to the assembler and the whitespace code ops:
@@ -120,10 +122,12 @@ See [Memory layout convention](#memory-layout-convention)
120122
### Bitwise
121123

122124
- `bitwise_and(a,b)`
125+
- `bitwise_xor(a,b)`
123126
- `bitwise_or(a,b)`
124127
- `bitwise_not(a)`
125-
- `bitwise_not_mod(a, m)`: Performs a bitwise not operation but only for the low `m` bytes.
128+
- `bitwise_not_mod(a, m)`: Performs a bitwise not operation but only for the low `m` bits.
126129
- `bitwise_mask(m)`: Creates a mask with `m` 1s (essentially 2^m-1)
130+
- `bitwise_rotl(n,m,bits)`: Rotates the number `n`, `m` positions to the left, with a mask of `bits` bits.
127131

128132
This library uses the language extensions if they are enabled, otherwise uses the standard 0.3 WS opcodes.
129133

@@ -137,3 +141,58 @@ This library uses the language extensions if they are enabled, otherwise uses th
137141
### Math
138142

139143
- `math_exp_2(v)`: Performs the operation 2^v
144+
145+
### Memcontainer
146+
147+
Small data structure to have a stable reference on other data structures that can get reallocated.
148+
149+
It basically allocates 2 blocks: The container that can grow in size (and maybe reallocated), and a 1-byte one that just has the pointer to the container. This way the fixed one will keep the same reference across reallocations.
150+
151+
To get the actual address, just `retrieve` to read the pointer value.
152+
153+
- `memcontainer_new(capacity)`: Initializes a new container with an initial `capacity`
154+
- `memcontainer_destroy(&container)`: Frees up the reference `&container`
155+
- `memcontainer_get_capacity(&container)`: Returns the current capacity of the container.
156+
- `memcontainer_ensure_capacity(&container, capacity)`: If the container has less than `capacity` capacity, it resizes it.
157+
158+
### Vector
159+
160+
Resizable data structure to add / remove items to a list. It keeps a stable reference through `memcontainer`.
161+
162+
- `vector_new(capacity)`: Creates a new vector
163+
- `vector_destroy(&vector)`: Frees up the reference `&vector`
164+
- `vector_fill(&vector, length, value)`: Fills in the vector with `value` for `length` (resizing the vector if needed).
165+
- `vector_get_addr(&vector)`: Returns the current base address of the vector.
166+
- `vector_get_capacity(&vector)`: Returns the capacity of the vector.
167+
- `vector_get_length(&vector)`: Returns the length of the vector.
168+
- `vector_set_length(&vector, length)`: Sets the length of the vector (truncating or resizing as needed).
169+
- `vector_push(&vector, value)`: Pushes the value to the vector.
170+
- `vector_pop(&vector)`: Pops the last element from the vector.
171+
- `vector_slice(&vector, offset, length)`: Returns a new vector with a copy from offset for `length` bytes.
172+
- `vector_splice(&vector, offset, length)`: Returns a new vector without the values from offset for `length` bytes.
173+
- `vector_push_all(&vector, &other_vec)`: Pushes all the elements of `&other_vec` to `&vector`
174+
175+
### Slotmap
176+
177+
Data structure to allocate and free fixed-size blocks a bit more efficiently than through the heap. Meant to build other data structures on top that perform a lot of small allocations (e.g. trees, linked lists, etc.).
178+
179+
- `slotmap_new(element_size)`: Creates a new slotmap for elements of `element_size` bytes.
180+
- `slotmap_destroy(&slotmap)`: Frees up the reference `&slotmap`.
181+
- `slotmap_allocate(&slotmap)`: Allocates a new block, returns its id.
182+
- `slotmap_free(&slotmap, id)`: Frees up the space for the block `id`.
183+
- `slotmap_get_addr(&slotmap, id)`: Returns the base address for the block `id`.
184+
185+
### RBTree
186+
187+
Key-value data structure using a simplified implementation of a red-black tree. Deletion doesn't guarantee to keep the tree balanced.
188+
189+
- `rbtree_new()`: Creates a new RBTree-
190+
- `rbtree_destroy(&RB)`: Frees up the reference `&RB`.
191+
- `rbtree_insert(&RB, key, value)`: Inserts a new entry with `key` and `value`.
192+
- `rbtree_get(&RB, key)`: Finds the entry by `key`, returns `[value,found]`, where found is 1 or 0 indicating if the value was found. If not found, `value` may have any random value.
193+
- `rbtree_remove(&RB, key)`: Removes the entry by `key`.
194+
- `rbtree_print(&RB)`: Prints the tree to the console (for debugging).
195+
- `rbtree_get_sorted(&RB)`: returns the entries [key,value] into a vector, sorted by key ascending.
196+
- `rbtree_is_empty(&RB)`: returns whether the tree is empty.
197+
- `rbtree_get_smallest(&RB)`: returns the entry with smallest key.
198+
- `rbtree_get_biggest(&RB)`: returns the entry with biggest key.

src/wsa/lib/rbtree.wsa

Lines changed: 121 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include slotmap
2+
include vector
23

34
; RED=1
45
; BLACK=0
@@ -630,7 +631,8 @@ label __rbtree_remove_node
630631
copy 1
631632
swap
632633
call slotmap_get_addr
633-
call __rbtree_find_smallest
634+
push __RBTREE_MASK_LEFT
635+
call __rbtree_find_extreme
634636
; [&RB,&node,&succesor]
635637
copy 1
636638
add 1
@@ -777,25 +779,136 @@ label __rbtree_remove_node
777779
call slotmap_free
778780
ret
779781

780-
; args &RB &node
781-
label __rbtree_find_smallest
782+
; args &RB
783+
label rbtree_is_empty
784+
push 0
785+
call slotmap_get_addr
786+
retrieve
787+
jumpz __rbtree_is_empty_empty
788+
push 0
789+
ret
790+
label __rbtree_is_empty_empty
791+
push 1
792+
ret
793+
794+
; args &RB
795+
; returns [key,value]
796+
label rbtree_get_smallest
797+
push __RBTREE_MASK_LEFT
798+
call __rbtree_get_extreme
799+
ret
800+
801+
; args &RB
802+
; returns [key,value]
803+
label rbtree_get_biggest
804+
push __RBTREE_MASK_RIGHT
805+
call __rbtree_get_extreme
806+
ret
807+
808+
809+
; args &RB dir
810+
; returns [key,value]
811+
label __rbtree_get_extreme
812+
copy 1
782813
dup
814+
push 0
815+
call slotmap_get_addr
783816
retrieve
784-
div __RBTREE_MASK_LEFT
817+
call slotmap_get_addr
818+
; [&RB, dir, &root]
819+
swap
820+
call __rbtree_find_extreme
821+
dup
822+
add 1
823+
retrieve
824+
swap
825+
add 2
826+
retrieve
827+
ret
828+
829+
; args &RB &node dir
830+
; returns &node
831+
label __rbtree_find_extreme
832+
copy 1
833+
retrieve
834+
swap
835+
div
785836
mod __RBTREE_MASK_MOD
786-
; [&RB,&node,node.left]
837+
; [&RB,&node,node[dir]]
787838
dup
788-
jumpz __rbtree_find_smallest_found
839+
jumpz __rbtree_find_extreme_found
789840
slide 1
790841
copy 1
791842
swap
792843
call slotmap_get_addr
793-
jump __rbtree_find_smallest
794-
label __rbtree_find_smallest_found
844+
jump __rbtree_find_extreme
845+
label __rbtree_find_extreme_found
795846
pop
796847
slide 1
797848
ret
798849

850+
; args &RB
851+
; returns &vec
852+
label rbtree_get_sorted
853+
push 5
854+
call vector_new
855+
swap
856+
; [&vec,&RB]
857+
copy 1
858+
copy 1 ; &RB
859+
push 0
860+
call slotmap_get_addr
861+
retrieve
862+
call __rbtree_push_sorted
863+
pop
864+
pop
865+
ret
866+
867+
; args &RB &vec node_id
868+
; returns &RB &vec
869+
label __rbtree_push_sorted
870+
dup
871+
jumpz __rbtree_push_sorted_leaf
872+
copy 2
873+
swap
874+
call slotmap_get_addr
875+
dup
876+
retrieve
877+
; [&RB,&vec,&node,node_header]
878+
copy 3
879+
copy 3
880+
; [&RB,&vec,&node,node_header,&RB,&vec]
881+
copy 2 ; node_header
882+
div __RBTREE_MASK_LEFT
883+
mod __RBTREE_MASK_MOD
884+
call __rbtree_push_sorted
885+
886+
; [&RB,&vec,&node,node_header,&RB,&vec]
887+
dup
888+
copy 4 ; &node
889+
add 1
890+
retrieve
891+
call vector_push
892+
dup
893+
copy 4 ; &node
894+
add 2
895+
retrieve
896+
call vector_push
897+
898+
; [&RB,&vec,&node,node_header,&RB,&vec]
899+
copy 2 ; node_header
900+
div __RBTREE_MASK_RIGHT
901+
mod __RBTREE_MASK_MOD
902+
call __rbtree_push_sorted
903+
904+
; [&RB,&vec,&node,node_header,&RB,&vec]
905+
slide 3
906+
pop
907+
ret
908+
label __rbtree_push_sorted_leaf
909+
pop
910+
ret
911+
799912
; args &RB &node parent_header
800913
; returns left/right mask
801914
label __rbtree_get_node_dir_by_ref

wsa-tests/rbtree.wsa

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ pop
2020
dup
2121
call rbtree_print
2222

23+
dup
24+
call rbtree_get_sorted
25+
call vector_destroy
26+
2327
push 8
2428
label loop2
2529
dup

0 commit comments

Comments
 (0)