Add more exercises
This commit is contained in:
+162
-105
@@ -42,67 +42,77 @@ Successful output of all the tests:
|
|||||||
#+BEGIN_SRC sh
|
#+BEGIN_SRC sh
|
||||||
$ make run 12:25PM
|
$ make run 12:25PM
|
||||||
[ 3%] Built target munit
|
[ 3%] Built target munit
|
||||||
[ 8%] Built target 8-6-multiple-types
|
[ 6%] Built target 9-8-length
|
||||||
[ 11%] Built target 4-1-enums
|
[ 7%] Built target 4-1-enums
|
||||||
[ 14%] Built target 4-2-non-default-values
|
[ 9%] Built target 4-2-non-default-values
|
||||||
[ 17%] Built target 4-3-switch-case
|
[ 12%] Built target 4-3-switch-case
|
||||||
[ 20%] Built target 4-4-sizeof-enum
|
[ 14%] Built target 4-4-sizeof-enum
|
||||||
[ 24%] Built target 5-1-union
|
[ 17%] Built target 5-1-union
|
||||||
[ 26%] Built target 5-2-memory-layout
|
[ 19%] Built target 5-2-memory-layout
|
||||||
[ 29%] Built target 5-3-5-4-union-size
|
[ 21%] Built target 5-3-5-4-union-size
|
||||||
[ 32%] Built target 5-5-helper-fields
|
[ 23%] Built target 5-5-helper-fields
|
||||||
[ 34%] Built target 6-1-the-stack
|
[ 25%] Built target 6-1-the-stack
|
||||||
[ 37%] Built target 6-2-why-a-stack
|
[ 27%] Built target 6-2-why-a-stack
|
||||||
[ 39%] Built target 6-3-stack-overflow
|
[ 29%] Built target 6-3-stack-overflow
|
||||||
[ 42%] Built target 6-4-pointers-to-the-stack
|
[ 31%] Built target 6-4-pointers-to-the-stack
|
||||||
[ 46%] Built target 6-5-the-heap
|
[ 34%] Built target 6-5-the-heap
|
||||||
[ 50%] Built target 6-6-malloc
|
[ 37%] Built target 6-6-malloc
|
||||||
[ 53%] Built target 6-7-free
|
[ 40%] Built target 6-7-free
|
||||||
[ 56%] Built target 6-8-big-endian-little-endian
|
[ 42%] Built target 6-8-big-endian-little-endian
|
||||||
[ 60%] Built target 7-1-pointer-pointers
|
[ 45%] Built target 7-1-pointer-pointers
|
||||||
[ 64%] Built target 7-2-array-of-pointers
|
[ 48%] Built target 7-2-array-of-pointers
|
||||||
[ 67%] Built target 7-3-void-pointers
|
[ 51%] Built target 7-3-void-pointers
|
||||||
[ 71%] Built target 7-4-swapping-integers
|
[ 54%] Built target 7-4-swapping-integers
|
||||||
[ 75%] Built target 7-5-swapping-strings
|
[ 57%] Built target 7-5-swapping-strings
|
||||||
[ 79%] Built target 7-6-generic-swap
|
[ 60%] Built target 7-6-generic-swap
|
||||||
[ 83%] Built target 8-1-low-level-stack
|
[ 63%] Built target 8-1-low-level-stack
|
||||||
[ 87%] Built target 8-2-stack-push
|
[ 66%] Built target 8-2-stack-push
|
||||||
[ 91%] Built target 8-3-stack-pop
|
[ 69%] Built target 8-3-stack-pop
|
||||||
[ 94%] Built target 8-4-stack-free
|
[ 72%] Built target 8-4-stack-free
|
||||||
[100%] Built target 8-5-dangerous-push
|
[ 76%] Built target 8-5-dangerous-push
|
||||||
Running test suite with seed 0x039ca6b1...
|
[ 80%] Built target 8-6-multiple-types
|
||||||
colors/are_defined [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
[ 82%] Built target 9-1-snek-objects
|
||||||
colors/are_defined_correctly [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
[ 85%] Built target 9-2-integer
|
||||||
|
[ 88%] Built target 9-3-float
|
||||||
|
[ 91%] Built target 9-4-string
|
||||||
|
[ 94%] Built target 9-5-vector3
|
||||||
|
[ 97%] Built target 9-6-arrays
|
||||||
|
[100%] Built target 9-7-get-and-set
|
||||||
|
Running test suite with seed 0xa13b83c4...
|
||||||
|
colors/are_defined [ OK ] [ 0.00000100 / 0.00000300 CPU ]
|
||||||
|
colors/are_defined_correctly [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0xbf68f4fa...
|
Running test suite with seed 0x9c11f043...
|
||||||
colors/defined [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
colors/defined [ OK ] [ 0.00000000 / 0.00000000 CPU ]
|
||||||
colors/defined_vscode [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
colors/defined_vscode [ OK ] [ 0.00000000 / 0.00000000 CPU ]
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0x40b17fef...
|
Running test suite with seed 0xdac57c79...
|
||||||
http/switch_enum [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
http/switch_enum [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
http/switch_enum_default [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
http/switch_enum_default [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
The size of BigNumbers is 8 bytes
|
The size of BigNumbers is 8 bytes
|
||||||
The size of HttpErrorCode is 4 bytes
|
The size of HttpErrorCode is 4 bytes
|
||||||
Running test suite with seed 0xde548fa9...
|
Running test suite with seed 0x85251cb1...
|
||||||
format/integer [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
format/integer [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
format/string [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
format/string [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
format/integer_nvim [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
format/integer_nvim [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
format/string_nvim [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
format/string_nvim [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
value (set): -420
|
value (set): -420
|
||||||
err (unset): 4294966876
|
err (unset): 4294966876
|
||||||
value (unset): -1
|
value (unset): -1
|
||||||
err (set): 4294967295
|
err (set): 4294967295
|
||||||
Running test suite with seed 0xa7197940...
|
Running test suite with seed 0xb2bd8586...
|
||||||
PacketHeader/test_packet_header_size [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
PacketHeader/test_packet_header_size [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
PacketHeader/test_tcp_header_fields [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
PacketHeader/test_tcp_header_fields [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
PacketHeader/test_field_raw_size [ OK ] [ 0.00000000 / 0.00000100 CPU ]
|
PacketHeader/test_field_raw_size [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
PacketHeader/test_field_to_raw_consistency[ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
PacketHeader/test_field_to_raw_consistency[ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
--------------------------------- Stack pointer offset: 0 bytes
|
---------------------------------
|
||||||
|
Stack pointer offset: 0 bytes
|
||||||
---------------------------------
|
---------------------------------
|
||||||
Dark mode?
|
Dark mode?
|
||||||
|
|
||||||
---------------------------------
|
---------------------------------
|
||||||
Stack pointer offset: 0 bytes
|
Stack pointer offset: 0 bytes
|
||||||
---------------------------------
|
---------------------------------
|
||||||
@@ -112,95 +122,142 @@ More like...
|
|||||||
Stack pointer offset: 0 bytes
|
Stack pointer offset: 0 bytes
|
||||||
---------------------------------
|
---------------------------------
|
||||||
dark roast.
|
dark roast.
|
||||||
Running test suite with seed 0x7dcfad3b...
|
|
||||||
/example/compare [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
Running test suite with seed 0x5ed24c16...
|
||||||
/example/rand [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
/example/compare [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
/example/rand [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
/example/parameters
|
/example/parameters
|
||||||
foo=one, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=one, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
foo=one, bar=green [ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
foo=one, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
foo=two, bar=red [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
foo=two, bar=red [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
foo=two, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ] foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=two, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
foo=three, bar=red [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
foo=three, bar=green [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
foo=three, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
foo=three, bar=blue [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
foo=three, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
foo=three, bar=blue [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
11 of 11 (100%) tests successful, 0 (0%) test skipped.
|
11 of 11 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Size of pool: 10240
|
Size of pool: 10240
|
||||||
Initial string: snek
|
Initial string: snek
|
||||||
c1: 10, 20
|
c1: 10, 20
|
||||||
c2: 30, 40
|
c2: 30, 40
|
||||||
c3: 50, 60 Running test suite with seed 0x53c7e720...
|
c3: 50, 60
|
||||||
get_full_greeting/test_basic_greeting[ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
Running test suite with seed 0x08ecbbe7...
|
||||||
get_full_greeting/test_short_buffer [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
get_full_greeting/test_basic_greeting[ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
get_full_greeting/test_short_buffer [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0xee42ee28...
|
Running test suite with seed 0xd953a05a...
|
||||||
allocate_scalar_array/test_allocate_scalar_array_size[ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
allocate_scalar_array/test_allocate_scalar_array_size[ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
allocate_scalar_array/test_allocate_scalar_array_values[ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
allocate_scalar_array/test_allocate_scalar_array_values[ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
allocate_scalar_array/test_allocate_scalar_array_zero_multiplier[ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
allocate_scalar_array/test_allocate_scalar_array_zero_multiplier[ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
allocate_scalar_array/test_allocate_too_much[ OK ] [ 0.00001000 / 0.00000900 CPU ]
|
allocate_scalar_array/test_allocate_too_much[ OK ] [ 0.00001000 / 0.00000900 CPU ]
|
||||||
4 of 4 (100%) tests successful, 0 (0%) test skipped. Allocated 500 lists
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0x9d78388e...
|
Allocated 500 lists
|
||||||
|
Running test suite with seed 0x026c49ea...
|
||||||
/example/compare [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
/example/compare [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
/example/rand [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
/example/rand [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
/example/parameters
|
/example/parameters
|
||||||
foo=one, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=one, bar=red [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
foo=one, bar=green [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
foo=one, bar=green [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
foo=one, bar=blue [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
foo=two, bar=red [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=two, bar=red [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
foo=two, bar=green [ OK ] [ 0.00000200 / 0.00000000 CPU ] foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
foo=two, bar=green [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
foo=three, bar=red [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
foo=three, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=three, bar=red [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
foo=three, bar=green [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
foo=three, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
foo=three, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
11 of 11 (100%) tests successful, 0 (0%) test skipped.
|
11 of 11 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0x07fdd526...
|
Running test suite with seed 0xbb38daad...
|
||||||
allocate_list/create [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
allocate_list/create [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
allocate_list/overwrite [ OK ] [ 0.00000100 / 0.00000100 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
allocate_list/overwrite [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
Running test suite with seed 0xf26a30e1...
|
|
||||||
create_token_pointer_array/test_create_token_pointer_array_single[ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
|
||||||
create_token_pointer_array/test_create_token_pointer_array_multiple[ OK ] [ 0.00000300 / 0.00000200 CPU ]
|
|
||||||
create_token_pointer_array/test_create_token_pointer_array_memory_allocation[ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
|
||||||
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
|
||||||
Running test suite with seed 0x4c18af41...
|
|
||||||
snek_zero_out/test_zero_out_integer [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
|
||||||
snek_zero_out/test_zero_out_float [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
|
||||||
snek_zero_out/test_zero_out_bool [ OK ] [ 0.00000100 / 0.00000000 CPU ] snek_zero_out/test_zero_out_nonzero_values[ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
|
||||||
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
|
||||||
Running test suite with seed 0xb0750720...
|
|
||||||
void-pointer/swap_ints [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
|
||||||
void-pointer/swap_ints_same [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0xc10a0ca0...
|
Running test suite with seed 0x33807c18...
|
||||||
|
create_token_pointer_array/test_create_token_pointer_array_single[ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
create_token_pointer_array/test_create_token_pointer_array_multiple[ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
create_token_pointer_array/test_create_token_pointer_array_memory_allocation[ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x8614a0d1...
|
||||||
|
snek_zero_out/test_zero_out_integer [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
snek_zero_out/test_zero_out_float [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
snek_zero_out/test_zero_out_bool [ OK ] [ 0.00000000 / 0.00000000 CPU ]
|
||||||
|
snek_zero_out/test_zero_out_nonzero_values[ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
||||||
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x2f6f82cf...
|
||||||
|
void-pointer/swap_ints [ OK ] [ 0.00000000 / 0.00000000 CPU ]
|
||||||
|
void-pointer/swap_ints_same [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x62099957...
|
||||||
void-pointer/swap_str [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
void-pointer/swap_str [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
void-pointer/test_swap_str_long [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
void-pointer/test_swap_str_long [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xa27e09af...
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
swap/generic_ints [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
Running test suite with seed 0x56ef9f75...
|
||||||
swap/generic_strings [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
swap/generic_ints [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
swap/generic_strings [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
swap/generic_struct [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
swap/generic_struct [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0xd1be93bf...
|
Running test suite with seed 0xdf070ee5...
|
||||||
snekstack/create_stack_small [ OK ] [ 0.00000100 / 0.00000000 CPU ]
|
snekstack/create_stack_small [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
snekstack/create_stack_large [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
snekstack/create_stack_large [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x92735306...
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
Running test suite with seed 0xa0778dac...
|
||||||
|
snekstack/create_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
snekstack/push_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
snekstack/push_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
snekstack/push_double_capacity [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
snekstack/push_double_capacity [ OK ] [ 0.00000300 / 0.00000300 CPU ]
|
||||||
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0xd641eade...
|
Running test suite with seed 0x1df97623...
|
||||||
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
snekstack/push_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
snekstack/push_stack [ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
||||||
snekstack/pop_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
snekstack/pop_stack [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
snekstack/pop_stack_empty [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
snekstack/pop_stack_empty [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
4 of 4 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0xd1d1136d...
|
Running test suite with seed 0xc67f74fb...
|
||||||
snekstack/create_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
snekstack/create_stack [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
snekstack/push_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
snekstack/push_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
snekstack/pop_stack [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
snekstack/pop_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0x5493a18d...
|
Running test suite with seed 0xb607698d...
|
||||||
snekstack/heterogenous_stack [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
snekstack/heterogenous_stack [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
||||||
Running test suite with seed 0x0dc3c3f9...
|
Running test suite with seed 0x4804e928...
|
||||||
snekstack/multiple_types_stack [ OK ] [ 0.00000300 / 0.00000200 CPU ]
|
snekstack/multiple_types_stack [ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
||||||
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xa5a077a3...
|
||||||
|
object-integer-def/integer_constant [ OK ] [ 0.00000000 / 0.00000100 CPU ]
|
||||||
|
object-integer-def/integer_obj [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x0a7224ef...
|
||||||
|
object-integer/positive [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
object-integer/zero [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
object-integer/negative [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x748c3598...
|
||||||
|
object-float/positive [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
object-float/zero [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
object-float/negative [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x4632a6a6...
|
||||||
|
object-string/copies_value [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
1 of 1 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x386735e2...
|
||||||
|
object-vector/returns_null [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
object-vector/multiple_objects [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
object-vector/same_object [ OK ] [ 0.00000100 / 0.00000200 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0x4e6badf5...
|
||||||
|
object-array/empty [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
object-array/calloc [ OK ] [ 0.00000100 / 0.00000100 CPU ]
|
||||||
|
2 of 2 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xe9625367...
|
||||||
|
object-array/set_and_get [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
object-array/set_outside [ OK ] [ 0.00000200 / 0.00000300 CPU ]
|
||||||
|
object-array/get_outside [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
3 of 3 (100%) tests successful, 0 (0%) test skipped.
|
||||||
|
Running test suite with seed 0xa7022b54...
|
||||||
|
object-length/integer [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
object-length/float [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
object-length/string [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
object-length/vector [ OK ] [ 0.00000200 / 0.00000200 CPU ]
|
||||||
|
object-length/array [ OK ] [ 0.00000200 / 0.00000100 CPU ]
|
||||||
|
5 of 5 (100%) tests successful, 0 (0%) test skipped.
|
||||||
[100%] Built target run
|
[100%] Built target run
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
// Q: Which language makes use of a garbage collector (automatic memory management)?
|
||||||
|
// A: Go
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_int_has_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_float_has_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(42.0);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("test_int_has_refcount", test_int_has_refcount),
|
||||||
|
munit_test("test_float_has_refcount", test_float_has_refcount),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("refcount", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
snek_object_t *_new_snek_object() {
|
||||||
|
snek_object_t *obj = (snek_object_t *)calloc(1, sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) return NULL;
|
||||||
|
obj->refcount = 1;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
size_t refcount;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
|
int snek_length(snek_object_t *obj);
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_inc_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_inc_refcount_more, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
refcount_inc(obj);
|
||||||
|
refcount_inc(obj);
|
||||||
|
refcount_inc(obj);
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 6, "Refcount should be incremented to 6");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_null_obj, {
|
||||||
|
refcount_inc(NULL);
|
||||||
|
assert(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/test_inc_refcount", test_inc_refcount),
|
||||||
|
munit_test("/test_inc_refcount_more", test_inc_refcount_more),
|
||||||
|
munit_test("/test_null_obj", test_null_obj),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("refcount", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) return;
|
||||||
|
obj->refcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
snek_object_t *_new_snek_object() {
|
||||||
|
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount = 1;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
size_t refcount;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
|
int snek_length(snek_object_t *obj);
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj);
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_int_has_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_inc_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_dec_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
|
// assert(!boot_is_freed(obj));
|
||||||
|
|
||||||
|
// Object is still alive, so we will free manually.
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_refcount_free_is_called, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
// assert(boot_is_freed(obj));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_allocated_string_is_freed, {
|
||||||
|
snek_object_t *obj = new_snek_string("Hello @wagslane!");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
// assert(boot_is_freed(obj));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/has_refcount", test_int_has_refcount),
|
||||||
|
munit_test("/inc_refcount", test_inc_refcount),
|
||||||
|
munit_test("/dec_refcount", test_dec_refcount),
|
||||||
|
munit_test("/free_refcount", test_refcount_free_is_called),
|
||||||
|
munit_test("/string_freed", test_allocated_string_is_freed),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("refcount", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
void refcount_dec(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) return;
|
||||||
|
obj->refcount--;
|
||||||
|
if (obj->refcount <= 0) refcount_free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcount_free(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) return;
|
||||||
|
if (obj->kind == INTEGER || obj->kind == FLOAT) {
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
if (obj->kind == STRING) {
|
||||||
|
free(obj->data.v_string);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *_new_snek_object() {
|
||||||
|
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount = 1;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
size_t refcount;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
|
int snek_length(snek_object_t *obj);
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj);
|
||||||
|
void refcount_dec(snek_object_t *obj);
|
||||||
|
void refcount_free(snek_object_t *obj);
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_vector3_refcounting, {
|
||||||
|
snek_object_t *foo = new_snek_integer(1);
|
||||||
|
snek_object_t *bar = new_snek_integer(2);
|
||||||
|
snek_object_t *baz = new_snek_integer(3);
|
||||||
|
|
||||||
|
snek_object_t *vec = new_snek_vector3(foo, bar, baz);
|
||||||
|
assert_int(foo->refcount, ==, 2, "foo is now referenced by vec");
|
||||||
|
assert_int(bar->refcount, ==, 2, "bar is now referenced by vec");
|
||||||
|
assert_int(baz->refcount, ==, 2, "baz is now referenced by vec");
|
||||||
|
|
||||||
|
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||||
|
refcount_dec(foo);
|
||||||
|
// assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
|
refcount_dec(vec);
|
||||||
|
// assert(boot_is_freed(foo));
|
||||||
|
|
||||||
|
// These are still alive, they have the original reference still.
|
||||||
|
// assert(!boot_is_freed(bar));
|
||||||
|
// assert(!boot_is_freed(baz));
|
||||||
|
|
||||||
|
// Decrement the last reference to the objects, so they will be freed.
|
||||||
|
refcount_dec(bar);
|
||||||
|
refcount_dec(baz);
|
||||||
|
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_vector3_refcounting_same, {
|
||||||
|
snek_object_t *foo = new_snek_integer(1);
|
||||||
|
|
||||||
|
snek_object_t *vec = new_snek_vector3(foo, foo, foo);
|
||||||
|
assert_int(foo->refcount, ==, 4, "foo is now referenced by vec x3");
|
||||||
|
|
||||||
|
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||||
|
refcount_dec(foo);
|
||||||
|
// assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
|
refcount_dec(vec);
|
||||||
|
// assert(boot_is_freed(foo));
|
||||||
|
// assert(boot_is_freed(vec));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_int_has_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_inc_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_dec_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
|
// assert(!boot_is_freed(obj));
|
||||||
|
|
||||||
|
// Object is still alive, so we will free manually.
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_refcount_free_is_called, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
// assert(boot_is_freed(obj));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_allocated_string_is_freed, {
|
||||||
|
snek_object_t *obj = new_snek_string("Hello @wagslane!");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
// assert(boot_is_freed(obj));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/has_refcount", test_int_has_refcount),
|
||||||
|
munit_test("/inc_refcount", test_inc_refcount),
|
||||||
|
munit_test("/dec_refcount", test_dec_refcount),
|
||||||
|
munit_test("/free_refcount", test_refcount_free_is_called),
|
||||||
|
munit_test("/string_freed", test_allocated_string_is_freed),
|
||||||
|
munit_test("/vector3", test_vector3_refcounting),
|
||||||
|
munit_test("/vector3-same", test_vector3_refcounting_same),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("refcount", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
snek_object_t *_new_snek_object();
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z)
|
||||||
|
{
|
||||||
|
if (x == NULL || y == NULL || z == NULL) return NULL;
|
||||||
|
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
refcount_inc(x);
|
||||||
|
refcount_inc(y);
|
||||||
|
refcount_inc(z);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcount_free(snek_object_t *obj)
|
||||||
|
{
|
||||||
|
switch (obj->kind) {
|
||||||
|
case INTEGER:
|
||||||
|
case FLOAT:
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
free(obj->data.v_string);
|
||||||
|
break;
|
||||||
|
case VECTOR3: {
|
||||||
|
refcount_dec(obj->data.v_vector3.x);
|
||||||
|
refcount_dec(obj->data.v_vector3.y);
|
||||||
|
refcount_dec(obj->data.v_vector3.z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcount_dec(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
obj->refcount--;
|
||||||
|
if (obj->refcount == 0) {
|
||||||
|
return refcount_free(obj);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *_new_snek_object() {
|
||||||
|
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount = 1;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
size_t refcount;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
|
int snek_length(snek_object_t *obj);
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj);
|
||||||
|
void refcount_dec(snek_object_t *obj);
|
||||||
|
void refcount_free(snek_object_t *obj);
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_array_set, {
|
||||||
|
snek_object_t *foo = new_snek_integer(1);
|
||||||
|
|
||||||
|
snek_object_t *array = new_snek_array(1);
|
||||||
|
snek_array_set(array, 0, foo);
|
||||||
|
assert_int(foo->refcount, ==, 2, "foo is now referenced by array");
|
||||||
|
|
||||||
|
// assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
|
refcount_dec(foo);
|
||||||
|
refcount_dec(array);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_array_free, {
|
||||||
|
snek_object_t *foo = new_snek_integer(1);
|
||||||
|
snek_object_t *bar = new_snek_integer(2);
|
||||||
|
snek_object_t *baz = new_snek_integer(3);
|
||||||
|
|
||||||
|
snek_object_t *array = new_snek_array(2);
|
||||||
|
snek_array_set(array, 0, foo);
|
||||||
|
snek_array_set(array, 1, bar);
|
||||||
|
assert_int(foo->refcount, ==, 2, "foo is now referenced by array");
|
||||||
|
assert_int(bar->refcount, ==, 2, "bar is now referenced by array");
|
||||||
|
assert_int(baz->refcount, ==, 1, "baz is not yet referenced by array");
|
||||||
|
|
||||||
|
// `foo` is stil referenced in the `array`, so it should not be freed.
|
||||||
|
refcount_dec(foo);
|
||||||
|
// assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
|
// Overwrite index 0, which is `foo`, with `baz`.
|
||||||
|
// Now `foo` is not referenced by `array`, so it should be freed.
|
||||||
|
snek_array_set(array, 0, baz);
|
||||||
|
// assert(boot_is_freed(foo));
|
||||||
|
|
||||||
|
refcount_dec(bar);
|
||||||
|
refcount_dec(baz);
|
||||||
|
refcount_dec(array);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_vector3_refcounting, {
|
||||||
|
snek_object_t *foo = new_snek_integer(1);
|
||||||
|
snek_object_t *bar = new_snek_integer(2);
|
||||||
|
snek_object_t *baz = new_snek_integer(3);
|
||||||
|
|
||||||
|
snek_object_t *vec = new_snek_vector3(foo, bar, baz);
|
||||||
|
assert_int(foo->refcount, ==, 2, "foo is now referenced by vec");
|
||||||
|
assert_int(bar->refcount, ==, 2, "bar is now referenced by vec");
|
||||||
|
assert_int(baz->refcount, ==, 2, "baz is now referenced by vec");
|
||||||
|
|
||||||
|
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||||
|
refcount_dec(foo);
|
||||||
|
// assert(!boot_is_freed(foo));
|
||||||
|
|
||||||
|
refcount_dec(vec);
|
||||||
|
// assert(boot_is_freed(foo));
|
||||||
|
|
||||||
|
// These are still alive, they have the original reference still.
|
||||||
|
// assert(!boot_is_freed(bar));
|
||||||
|
// assert(!boot_is_freed(baz));
|
||||||
|
|
||||||
|
// Decrement the last reference to the objects, so they will be freed.
|
||||||
|
refcount_dec(bar);
|
||||||
|
refcount_dec(baz);
|
||||||
|
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_int_has_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_integer(10);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_inc_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_dec_refcount, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
|
// assert(!boot_is_freed(obj));
|
||||||
|
|
||||||
|
// Object is still alive, so we will free manually.
|
||||||
|
free(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_refcount_free_is_called, {
|
||||||
|
snek_object_t *obj = new_snek_float(4.20);
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
// assert(boot_is_freed(obj));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_allocated_string_is_freed, {
|
||||||
|
snek_object_t *obj = new_snek_string("Hello @wagslane!");
|
||||||
|
|
||||||
|
refcount_inc(obj);
|
||||||
|
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||||
|
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||||
|
|
||||||
|
refcount_dec(obj);
|
||||||
|
// assert(boot_is_freed(obj));
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/array_set", test_array_set),
|
||||||
|
munit_test("/array_free", test_array_free),
|
||||||
|
munit_test("/has_refcount", test_int_has_refcount),
|
||||||
|
munit_test("/inc_refcount", test_inc_refcount),
|
||||||
|
munit_test("/dec_refcount", test_dec_refcount),
|
||||||
|
munit_test("/free_refcount", test_refcount_free_is_called),
|
||||||
|
munit_test("/string_freed", test_allocated_string_is_freed),
|
||||||
|
munit_test("/vector3", test_vector3_refcounting),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("refcount", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value)
|
||||||
|
{
|
||||||
|
if (snek_obj == NULL || value == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (snek_obj->kind != ARRAY) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (index >= snek_obj->data.v_array.size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (snek_obj->data.v_array.elements[index] != NULL) {
|
||||||
|
refcount_dec(snek_obj->data.v_array.elements[index]);
|
||||||
|
}
|
||||||
|
snek_obj->data.v_array.elements[index] = value;
|
||||||
|
refcount_inc(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcount_free(snek_object_t *obj)
|
||||||
|
{
|
||||||
|
switch (obj->kind) {
|
||||||
|
case INTEGER:
|
||||||
|
case FLOAT:
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
free(obj->data.v_string);
|
||||||
|
break;
|
||||||
|
case VECTOR3: {
|
||||||
|
snek_vector_t vec = obj->data.v_vector3;
|
||||||
|
refcount_dec(vec.x);
|
||||||
|
refcount_dec(vec.y);
|
||||||
|
refcount_dec(vec.z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARRAY: {
|
||||||
|
for (int i = 0; i < obj->data.v_array.size; i++) {
|
||||||
|
refcount_dec(obj->data.v_array.elements[i]);
|
||||||
|
}
|
||||||
|
free(obj->data.v_array.elements);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index) {
|
||||||
|
if (snek_obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snek_obj->kind != ARRAY) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= snek_obj->data.v_array.size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return snek_obj->data.v_array.elements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcount_dec(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
obj->refcount--;
|
||||||
|
if (obj->refcount == 0) {
|
||||||
|
return refcount_free(obj);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *_new_snek_object() {
|
||||||
|
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->refcount = 1;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
snek_object_t *obj = _new_snek_object();
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
refcount_inc(x);
|
||||||
|
refcount_inc(y);
|
||||||
|
refcount_inc(z);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
size_t refcount;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
|
int snek_length(snek_object_t *obj);
|
||||||
|
|
||||||
|
void refcount_inc(snek_object_t *obj);
|
||||||
|
void refcount_dec(snek_object_t *obj);
|
||||||
|
void refcount_free(snek_object_t *obj);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
// Q: Why doesn't the snek_add function need to take care of
|
||||||
|
// garbage collecting the resulting object?
|
||||||
|
|
||||||
|
// A:
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_create_empty_array, {
|
||||||
|
snek_object_t *obj = new_snek_array(2);
|
||||||
|
|
||||||
|
assert_int(obj->kind, ==, ARRAY, "Must set type to ARRAY");
|
||||||
|
assert_int(obj->data.v_array.size, ==, 2, "Must set size to 2");
|
||||||
|
|
||||||
|
free(obj->data.v_array.elements);
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_used_calloc, {
|
||||||
|
snek_object_t *obj = new_snek_array(2);
|
||||||
|
|
||||||
|
assert_ptr_null(obj->data.v_array.elements[0], "Should use calloc");
|
||||||
|
assert_ptr_null(obj->data.v_array.elements[1], "Should use calloc");
|
||||||
|
|
||||||
|
free(obj->data.v_array.elements);
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/empty", test_create_empty_array),
|
||||||
|
munit_test("/calloc", test_used_calloc),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("object-array", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) return NULL;
|
||||||
|
|
||||||
|
snek_object_t **arr = (snek_object_t **)calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (arr == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){ .size = size, .elements = arr };
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_array, {
|
||||||
|
// Create an array
|
||||||
|
snek_object_t *obj = new_snek_array(2);
|
||||||
|
|
||||||
|
// Create some objects to put in the array
|
||||||
|
// Can store objects, even though they have different types (just like Python)
|
||||||
|
snek_object_t *first = new_snek_string("First");
|
||||||
|
snek_object_t *second = new_snek_integer(3);
|
||||||
|
|
||||||
|
assert(snek_array_set(obj, 0, first));
|
||||||
|
assert(snek_array_set(obj, 1, second));
|
||||||
|
|
||||||
|
snek_object_t *retrieved_first = snek_array_get(obj, 0);
|
||||||
|
assert_not_null(retrieved_first, "Should find the first object");
|
||||||
|
assert_int(retrieved_first->kind, ==, STRING, "Should be a string");
|
||||||
|
assert_ptr(first, ==, retrieved_first, "Should be the same object");
|
||||||
|
|
||||||
|
snek_object_t *retrieved_second = snek_array_get(obj, 1);
|
||||||
|
assert_not_null(retrieved_second, "Should find the second object");
|
||||||
|
assert_int(retrieved_second->kind, ==, INTEGER, "Should be a integer");
|
||||||
|
assert_ptr(second, ==, retrieved_second, "Should be the same object");
|
||||||
|
|
||||||
|
free(first->data.v_string);
|
||||||
|
free(first);
|
||||||
|
free(second);
|
||||||
|
free(obj->data.v_array.elements);
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_set_outside_bounds, {
|
||||||
|
// Create an array
|
||||||
|
snek_object_t *obj = new_snek_array(2);
|
||||||
|
|
||||||
|
snek_object_t *outside = new_snek_string("First");
|
||||||
|
|
||||||
|
// Inside of bound
|
||||||
|
assert(snek_array_set(obj, 1, outside));
|
||||||
|
|
||||||
|
// Outside of bound
|
||||||
|
assert_false(snek_array_set(obj, 100, outside));
|
||||||
|
|
||||||
|
// Free memory
|
||||||
|
free(outside->data.v_string);
|
||||||
|
free(outside);
|
||||||
|
free(obj->data.v_array.elements);
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_get_outside_bounds, {
|
||||||
|
// Create an array
|
||||||
|
snek_object_t *obj = new_snek_array(1);
|
||||||
|
snek_object_t *first = new_snek_string("First");
|
||||||
|
assert(snek_array_set(obj, 0, first));
|
||||||
|
|
||||||
|
// Outside of bound
|
||||||
|
assert_null(snek_array_get(obj, 1), "Should not access outside the array");
|
||||||
|
|
||||||
|
free(first->data.v_string);
|
||||||
|
free(first);
|
||||||
|
free(obj->data.v_array.elements);
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/set_and_get", test_array),
|
||||||
|
munit_test("/set_outside", test_set_outside_bounds),
|
||||||
|
munit_test("/get_outside", test_get_outside_bounds),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("object-array", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value) {
|
||||||
|
if (snek_obj == NULL || value == NULL) return false;
|
||||||
|
if (snek_obj->kind != ARRAY) return false;
|
||||||
|
if (snek_obj->data.v_array.size <= index) return false;
|
||||||
|
|
||||||
|
snek_obj->data.v_array.elements[index] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index) {
|
||||||
|
if (snek_obj == NULL) return NULL;
|
||||||
|
if (snek_obj->kind != ARRAY) return NULL;
|
||||||
|
if (snek_obj->data.v_array.size <= index) return NULL;
|
||||||
|
|
||||||
|
return snek_obj->data.v_array.elements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#include "munit.h"
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
munit_case(RUN, test_integer, {
|
||||||
|
snek_object_t *obj = new_snek_integer(42);
|
||||||
|
assert_int(snek_length(obj), ==, 1, "Integers are length 1");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_float, {
|
||||||
|
snek_object_t *obj = new_snek_float(3.14);
|
||||||
|
assert_int(snek_length(obj), ==, 1, "Floats are length 1");
|
||||||
|
|
||||||
|
free(obj);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(RUN, test_string, {
|
||||||
|
snek_object_t *shorter = new_snek_string("hello");
|
||||||
|
assert_int(snek_length(shorter), ==, 5, "Should return based on input");
|
||||||
|
|
||||||
|
snek_object_t *longer = new_snek_string("hello, world");
|
||||||
|
assert_int(
|
||||||
|
snek_length(longer), ==, strlen("hello, world"), "Should use strlen"
|
||||||
|
);
|
||||||
|
|
||||||
|
free(shorter->data.v_string);
|
||||||
|
free(shorter);
|
||||||
|
free(longer->data.v_string);
|
||||||
|
free(longer);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_vector3, {
|
||||||
|
snek_object_t *i = new_snek_integer(1);
|
||||||
|
snek_object_t *vec = new_snek_vector3(i, i, i);
|
||||||
|
assert_int(snek_length(vec), ==, 3, "Vec3 always has length 3");
|
||||||
|
|
||||||
|
free(i);
|
||||||
|
free(vec);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
munit_case(SUBMIT, test_array, {
|
||||||
|
snek_object_t *i = new_snek_integer(1);
|
||||||
|
snek_object_t *arr = new_snek_array(4);
|
||||||
|
assert(snek_array_set(arr, 0, i));
|
||||||
|
assert(snek_array_set(arr, 1, i));
|
||||||
|
assert(snek_array_set(arr, 2, i));
|
||||||
|
|
||||||
|
assert_int(snek_length(arr), ==, 4, "Length of array should be its size");
|
||||||
|
|
||||||
|
free(i);
|
||||||
|
free(arr->data.v_array.elements);
|
||||||
|
free(arr);
|
||||||
|
// assert(boot_all_freed());
|
||||||
|
});
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MunitTest tests[] = {
|
||||||
|
munit_test("/integer", test_integer),
|
||||||
|
munit_test("/float", test_float),
|
||||||
|
munit_test("/string", test_string),
|
||||||
|
munit_test("/vector", test_vector3),
|
||||||
|
munit_test("/array", test_array),
|
||||||
|
munit_null_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
MunitSuite suite = munit_suite("object-length", tests);
|
||||||
|
|
||||||
|
return munit_suite_main(&suite, NULL, 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "snekobject.h"
|
||||||
|
|
||||||
|
int snek_length(snek_object_t *obj) {
|
||||||
|
if (obj == NULL) return -1;
|
||||||
|
if (obj->kind == INTEGER || obj->kind == FLOAT) return 1;
|
||||||
|
if (obj->kind == STRING) return strlen(obj->data.v_string);
|
||||||
|
if (obj->kind == VECTOR3) return 3;
|
||||||
|
if (obj->kind == ARRAY) return obj->data.v_array.size;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't touch below this line
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||||
|
if (elements == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = ARRAY;
|
||||||
|
obj->data.v_array = (snek_array_t){.size = size, .elements = elements};
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool snek_array_set(snek_object_t *array, size_t index, snek_object_t *value) {
|
||||||
|
if (array == NULL || value == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array->kind != ARRAY) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= array->data.v_array.size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value directly now (already checked size constraint)
|
||||||
|
array->data.v_array.elements[index] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *array, size_t index) {
|
||||||
|
if (array == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array->kind != ARRAY) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= array->data.v_array.size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value directly now (already checked size constraint)
|
||||||
|
return array->data.v_array.elements[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_vector3(
|
||||||
|
snek_object_t *x, snek_object_t *y, snek_object_t *z
|
||||||
|
) {
|
||||||
|
if (x == NULL || y == NULL || z == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = VECTOR3;
|
||||||
|
obj->data.v_vector3 = (snek_vector_t){.x = x, .y = y, .z = z};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = INTEGER;
|
||||||
|
obj->data.v_int = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_float(float value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->kind = FLOAT;
|
||||||
|
obj->data.v_float = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
snek_object_t *new_snek_string(char *value) {
|
||||||
|
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||||
|
if (obj == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(value);
|
||||||
|
char *dst = malloc(len + 1);
|
||||||
|
if (dst == NULL) {
|
||||||
|
free(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dst, value);
|
||||||
|
|
||||||
|
obj->kind = STRING;
|
||||||
|
obj->data.v_string = dst;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct SnekObject snek_object_t;
|
||||||
|
|
||||||
|
typedef enum SnekObjectKind {
|
||||||
|
INTEGER,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
VECTOR3,
|
||||||
|
ARRAY,
|
||||||
|
} snek_object_kind_t;
|
||||||
|
|
||||||
|
typedef struct SnekVector {
|
||||||
|
snek_object_t *x;
|
||||||
|
snek_object_t *y;
|
||||||
|
snek_object_t *z;
|
||||||
|
} snek_vector_t;
|
||||||
|
|
||||||
|
typedef struct SnekArray {
|
||||||
|
size_t size;
|
||||||
|
snek_object_t **elements;
|
||||||
|
} snek_array_t;
|
||||||
|
|
||||||
|
typedef union SnekObjectData {
|
||||||
|
int v_int;
|
||||||
|
float v_float;
|
||||||
|
char* v_string;
|
||||||
|
snek_vector_t v_vector3;
|
||||||
|
snek_array_t v_array;
|
||||||
|
} snek_object_data_t;
|
||||||
|
|
||||||
|
typedef struct SnekObject {
|
||||||
|
snek_object_kind_t kind;
|
||||||
|
snek_object_data_t data;
|
||||||
|
} snek_object_t;
|
||||||
|
|
||||||
|
snek_object_t *new_snek_integer(int value);
|
||||||
|
snek_object_t *new_snek_float(float value);
|
||||||
|
snek_object_t *new_snek_string(char *value);
|
||||||
|
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z);
|
||||||
|
|
||||||
|
snek_object_t *new_snek_array(size_t size);
|
||||||
|
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value);
|
||||||
|
snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index);
|
||||||
|
int snek_length(snek_object_t *obj);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||||
#include "../vendor/munit/munit.h"
|
#include "../vendor/munit/munit.h"
|
||||||
|
|
||||||
// TJ seems to have added a bunch of macros to the default munit.h,
|
// TJ seems to have added a bunch of macros to the default munit.h,
|
||||||
@@ -99,6 +100,9 @@
|
|||||||
#undef assert_null
|
#undef assert_null
|
||||||
#define assert_null(PTR, MSG) munit_assert_null(PTR, MSG)
|
#define assert_null(PTR, MSG) munit_assert_null(PTR, MSG)
|
||||||
|
|
||||||
|
#undef assert_not_null
|
||||||
|
#define assert_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG)
|
||||||
|
|
||||||
// ptr
|
// ptr
|
||||||
|
|
||||||
#undef munit_assert_ptr_not_equal
|
#undef munit_assert_ptr_not_equal
|
||||||
@@ -108,6 +112,10 @@
|
|||||||
#undef assert_ptr
|
#undef assert_ptr
|
||||||
#define assert_ptr(A, OP, B, MSG) munit_assert_ptr(A, OP, B)
|
#define assert_ptr(A, OP, B, MSG) munit_assert_ptr(A, OP, B)
|
||||||
|
|
||||||
|
#undef assert_ptr_null
|
||||||
|
#define assert_ptr_null(PTR, MSG) munit_assert_ptr_null(PTR)
|
||||||
|
// https://github.com/nemequ/munit/pull/73/files
|
||||||
|
|
||||||
#undef assert_ptr_not_null
|
#undef assert_ptr_not_null
|
||||||
#define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG)
|
#define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user