Compare commits
	
		
			7 Commits 
		
	
	
		
			215c1849f1
			...
			780996458b
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						780996458b | 2 months ago | 
| 
							
							
								 | 
						ba0d496a3c | 2 months ago | 
| 
							
							
								 | 
						0f94ca2909 | 2 months ago | 
| 
							
							
								 | 
						ec77cf9a1d | 2 months ago | 
| 
							
							
								 | 
						8d203036f7 | 2 months ago | 
| 
							
							
								 | 
						4e6cd60609 | 2 months ago | 
| 
							
							
								 | 
						7e909b73fb | 2 months ago | 
				 194 changed files with 8452 additions and 6 deletions
			
			
		@ -0,0 +1,388 @@ | 
				
			|||||||
 | 
					#+TITLE: Learn Memory Management in C | 
				
			||||||
 | 
					#+AUTHOR: Riyyi | 
				
			||||||
 | 
					#+LANGUAGE: en | 
				
			||||||
 | 
					#+OPTIONS: toc:nil | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Completed course from | 
				
			||||||
 | 
					[[https://www.boot.dev/courses/learn-memory-management-c][boot.dev]]. | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The exercises from the course have been worked out in this repository. | 
				
			||||||
 | 
					This is my way of obtaining the "certificate" for free. | 
				
			||||||
 | 
					The first the 3 chapters of the course can be done interactively on the website. | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[./bootdev-c.png]] | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you're reading this with the intention of completing the exercises yourself, | 
				
			||||||
 | 
					you can find each exercise is in its own directory inside of the =src= directory. | 
				
			||||||
 | 
					Remove all the files that each exercise mentions you should modify, as you go | 
				
			||||||
 | 
					through them. Then recreate the files from the exercise, so you won't get spoiled. | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Notes: | 
				
			||||||
 | 
					- In order to verify allocations in the unit tests, please use the wrapper | 
				
			||||||
 | 
					  functions =boot_malloc=, =boot_calloc=, =boot_realloc= and =boot_free= from | 
				
			||||||
 | 
					 =boot_lib.h= instead of the =stdlib.h= allocation functions | 
				
			||||||
 | 
					- In chapter 6 exercise 6, macOS malloc will almost never return a NULL pointer | 
				
			||||||
 | 
					  due to virtual memory overcommit, so you should check for | 
				
			||||||
 | 
					 ~size == 1024 * 1024 * 100)~ instead of ~array == NULL~ | 
				
			||||||
 | 
					- In chapter 8 and 11, I renamed ~stack_t~ to ~my_stack_t~ due to a =std= naming | 
				
			||||||
 | 
					  conflict on macOS | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					** Build instructions | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Compiling and running all the tests can be done with the following commands: | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#+BEGIN_SRC sh | 
				
			||||||
 | 
					$ mkdir build | 
				
			||||||
 | 
					$ cd build | 
				
			||||||
 | 
					$ cmake .. | 
				
			||||||
 | 
					$ make run | 
				
			||||||
 | 
					#+END_SRC | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					** Output | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Successful output of all the tests: | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#+BEGIN_SRC sh | 
				
			||||||
 | 
					$ make run                                                                                                                                                                                     12:25PM | 
				
			||||||
 | 
					[  2%] Built target munit | 
				
			||||||
 | 
					[  5%] Built target 11-10-sweep | 
				
			||||||
 | 
					[  6%] Built target 04-1-enums | 
				
			||||||
 | 
					[  7%] Built target 04-2-non-default-values | 
				
			||||||
 | 
					[  9%] Built target 04-3-switch-case | 
				
			||||||
 | 
					[ 10%] Built target 04-4-sizeof-enum | 
				
			||||||
 | 
					[ 12%] Built target 05-1-union | 
				
			||||||
 | 
					[ 13%] Built target 05-2-memory-layout | 
				
			||||||
 | 
					[ 15%] Built target 05-3-5-4-union-size | 
				
			||||||
 | 
					[ 16%] Built target 05-5-helper-fields | 
				
			||||||
 | 
					[ 17%] Built target 06-1-the-stack | 
				
			||||||
 | 
					[ 19%] Built target 06-2-why-a-stack | 
				
			||||||
 | 
					[ 20%] Built target 06-3-stack-overflow | 
				
			||||||
 | 
					[ 21%] Built target 06-4-pointers-to-the-stack | 
				
			||||||
 | 
					[ 23%] Built target 06-5-the-heap | 
				
			||||||
 | 
					[ 25%] Built target 06-6-malloc | 
				
			||||||
 | 
					[ 27%] Built target 06-7-free | 
				
			||||||
 | 
					[ 28%] Built target 06-8-big-endian-little-endian | 
				
			||||||
 | 
					[ 30%] Built target 07-1-pointer-pointers | 
				
			||||||
 | 
					[ 32%] Built target 07-2-array-of-pointers | 
				
			||||||
 | 
					[ 33%] Built target 07-3-void-pointers | 
				
			||||||
 | 
					[ 35%] Built target 07-4-swapping-integers | 
				
			||||||
 | 
					[ 37%] Built target 07-5-swapping-strings | 
				
			||||||
 | 
					[ 39%] Built target 07-6-generic-swap | 
				
			||||||
 | 
					[ 41%] Built target 08-1-low-level-stack | 
				
			||||||
 | 
					[ 42%] Built target 08-2-stack-push | 
				
			||||||
 | 
					[ 44%] Built target 08-3-stack-pop | 
				
			||||||
 | 
					[ 46%] Built target 08-4-stack-free | 
				
			||||||
 | 
					[ 48%] Built target 08-5-dangerous-push | 
				
			||||||
 | 
					[ 50%] Built target 08-6-multiple-types | 
				
			||||||
 | 
					[ 52%] Built target 09-1-snek-objects | 
				
			||||||
 | 
					[ 53%] Built target 09-2-integer | 
				
			||||||
 | 
					[ 55%] Built target 09-3-float | 
				
			||||||
 | 
					[ 57%] Built target 09-4-string | 
				
			||||||
 | 
					[ 59%] Built target 09-5-vector3 | 
				
			||||||
 | 
					[ 61%] Built target 09-6-arrays | 
				
			||||||
 | 
					[ 62%] Built target 09-7-get-and-set | 
				
			||||||
 | 
					[ 64%] Built target 09-8-length | 
				
			||||||
 | 
					[ 65%] Built target 10-1-garbage-collector | 
				
			||||||
 | 
					[ 67%] Built target 10-2-refcounting | 
				
			||||||
 | 
					[ 69%] Built target 10-3-increment | 
				
			||||||
 | 
					[ 71%] Built target 10-4-decrement-and-free | 
				
			||||||
 | 
					[ 73%] Built target 10-5-vectors | 
				
			||||||
 | 
					[ 74%] Built target 10-6-arrays | 
				
			||||||
 | 
					[ 76%] Built target 10-7-refcounting-review | 
				
			||||||
 | 
					[ 77%] Built target 11-01-handling-cycles | 
				
			||||||
 | 
					[ 80%] Built target 11-02-pros-and-cons | 
				
			||||||
 | 
					[ 82%] Built target 11-03-stack-frames | 
				
			||||||
 | 
					[ 85%] Built target 11-04-tracking-objects | 
				
			||||||
 | 
					[ 88%] Built target 11-05-free | 
				
			||||||
 | 
					[ 91%] Built target 11-06-frame-references | 
				
			||||||
 | 
					[ 94%] Built target 11-07-mark-and-sweep | 
				
			||||||
 | 
					[ 97%] Built target 11-08-mark | 
				
			||||||
 | 
					[100%] Built target 11-09-trace | 
				
			||||||
 | 
					Running test suite with seed 0x3d418efb... | 
				
			||||||
 | 
					colors/are_defined                   [ OK    ] [ 0.00000100 / 0.00000100 CPU ] | 
				
			||||||
 | 
					colors/are_defined_correctly         [ OK    ] [ 0.00000100 / 0.00000200 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x1447c343... | 
				
			||||||
 | 
					colors/defined                       [ OK    ] [ 0.00000000 / 0.00000100 CPU ] | 
				
			||||||
 | 
					colors/defined_vscode                [ OK    ] [ 0.00000100 / 0.00000200 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xba550ddb... | 
				
			||||||
 | 
					http/switch_enum                     [ OK    ] [ 0.00000100 / 0.00000100 CPU ] | 
				
			||||||
 | 
					http/switch_enum_default             [ OK    ] [ 0.00000100 / 0.00000200 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					The size of BigNumbers is 8 bytes | 
				
			||||||
 | 
					The size of HttpErrorCode is 4 bytes | 
				
			||||||
 | 
					Running test suite with seed 0xba8a2b8d... | 
				
			||||||
 | 
					format/integer                       [ OK    ] [ 0.00000200 / 0.00000300 CPU ] | 
				
			||||||
 | 
					format/string                        [ OK    ] [ 0.00000100 / 0.00000100 CPU ] | 
				
			||||||
 | 
					format/integer_nvim                  [ OK    ] [ 0.00000200 / 0.00000200 CPU ] | 
				
			||||||
 | 
					format/string_nvim                   [ OK    ] [ 0.00000100 / 0.00000200 CPU ] | 
				
			||||||
 | 
					4 of 4 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					value (set): -420 | 
				
			||||||
 | 
					err (unset): 4294966876 | 
				
			||||||
 | 
					value (unset): -1 | 
				
			||||||
 | 
					err (set): 4294967295 | 
				
			||||||
 | 
					Running test suite with seed 0xa0f30fc8... | 
				
			||||||
 | 
					PacketHeader/test_packet_header_size [ OK    ] [ 0.00000100 / 0.00000100 CPU ] | 
				
			||||||
 | 
					PacketHeader/test_tcp_header_fields  [ OK    ] [ 0.00000100 / 0.00000100 CPU ] | 
				
			||||||
 | 
					PacketHeader/test_field_raw_size     [ OK    ] [ 0.00000100 / 0.00000000 CPU ] | 
				
			||||||
 | 
					PacketHeader/test_field_to_raw_consistency[ OK    ] [ 0.00000100 / 0.00000000 CPU ] | 
				
			||||||
 | 
					4 of 4 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					--------------------------------- | 
				
			||||||
 | 
					Stack pointer offset: 0 bytes | 
				
			||||||
 | 
					--------------------------------- | 
				
			||||||
 | 
					Dark mode? | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--------------------------------- | 
				
			||||||
 | 
					Stack pointer offset: 0 bytes | 
				
			||||||
 | 
					--------------------------------- | 
				
			||||||
 | 
					More like... | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--------------------------------- | 
				
			||||||
 | 
					Stack pointer offset: 0 bytes | 
				
			||||||
 | 
					--------------------------------- | 
				
			||||||
 | 
					dark roast. | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Running test suite with seed 0xbd38a5fa... | 
				
			||||||
 | 
					/example/compare                     [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					/example/rand                        [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					/example/parameters | 
				
			||||||
 | 
					  foo=one, bar=red                   [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=green                 [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=blue                  [ OK    ] [ 0.00000200 / 0.00000300 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=red                   [ OK    ] [ 0.00000300 / 0.00000200 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=green                 [ OK    ] [ 0.00000200 / 0.00000200 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=blue                  [ OK    ] [ 0.00000200 / 0.00000200 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=red                 [ OK    ] [ 0.00000100 / 0.00000200 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=green               [ OK    ] [ 0.00000300 / 0.00000200 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=blue                [ OK    ] [ 0.00000200 / 0.00000300 CPU ] | 
				
			||||||
 | 
					11 of 11 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Size of pool: 10240 | 
				
			||||||
 | 
					Initial string: snek | 
				
			||||||
 | 
					c1: 10, 20 | 
				
			||||||
 | 
					c2: 30, 40 | 
				
			||||||
 | 
					c3: 50, 60 | 
				
			||||||
 | 
					Running test suite with seed 0x4e7eb250... | 
				
			||||||
 | 
					get_full_greeting/test_basic_greeting[ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					get_full_greeting/test_short_buffer  [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x98ffe6c3... | 
				
			||||||
 | 
					allocate_scalar_array/test_allocate_scalar_array_size[ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					allocate_scalar_array/test_allocate_scalar_array_values[ OK    ] [ 0.00000300 / 0.00000400 CPU ] | 
				
			||||||
 | 
					allocate_scalar_array/test_allocate_scalar_array_zero_multiplier[ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					allocate_scalar_array/test_allocate_too_much[ OK    ] [ 0.00001800 / 0.00001800 CPU ] | 
				
			||||||
 | 
					4 of 4 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Allocated 500 lists | 
				
			||||||
 | 
					Running test suite with seed 0xd142494f... | 
				
			||||||
 | 
					/example/compare                     [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					/example/rand                        [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					/example/parameters | 
				
			||||||
 | 
					  foo=one, bar=red                   [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=green                 [ OK    ] [ 0.00000600 / 0.00000700 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=blue                  [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=red                   [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=green                 [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=blue                  [ OK    ] [ 0.00000500 / 0.00000600 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=red                 [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=green               [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=blue                [ OK    ] [ 0.00001100 / 0.00001100 CPU ] | 
				
			||||||
 | 
					11 of 11 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x3b94faee... | 
				
			||||||
 | 
					allocate_list/create                 [ OK    ] [ 0.00000500 / 0.00000600 CPU ] | 
				
			||||||
 | 
					allocate_list/overwrite              [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x30623318... | 
				
			||||||
 | 
					create_token_pointer_array/test_create_token_pointer_array_single[ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					create_token_pointer_array/test_create_token_pointer_array_multiple[ OK    ] [ 0.00000600 / 0.00000700 CPU ] | 
				
			||||||
 | 
					create_token_pointer_array/test_create_token_pointer_array_memory_allocation[ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xdb4dc3bb... | 
				
			||||||
 | 
					snek_zero_out/test_zero_out_integer  [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					snek_zero_out/test_zero_out_float    [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					snek_zero_out/test_zero_out_bool     [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					snek_zero_out/test_zero_out_nonzero_values[ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					4 of 4 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x1e23c270... | 
				
			||||||
 | 
					void-pointer/swap_ints               [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					void-pointer/swap_ints_same          [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x343e18c2... | 
				
			||||||
 | 
					void-pointer/swap_str                [ OK    ] [ 0.00000400 / 0.00000500 CPU ] | 
				
			||||||
 | 
					void-pointer/test_swap_str_long      [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x349b3cc2... | 
				
			||||||
 | 
					swap/generic_ints                    [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					swap/generic_strings                 [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					swap/generic_struct                  [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xcc7f57e3... | 
				
			||||||
 | 
					snekstack/create_stack_small         [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					snekstack/create_stack_large         [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xb54c2f05... | 
				
			||||||
 | 
					snekstack/create_stack               [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					snekstack/push_stack                 [ OK    ] [ 0.00000700 / 0.00000600 CPU ] | 
				
			||||||
 | 
					snekstack/push_double_capacity       [ OK    ] [ 0.00000900 / 0.00000900 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x986e20e8... | 
				
			||||||
 | 
					snekstack/create_stack               [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					snekstack/push_stack                 [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					snekstack/pop_stack                  [ OK    ] [ 0.00000600 / 0.00000700 CPU ] | 
				
			||||||
 | 
					snekstack/pop_stack_empty            [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					4 of 4 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xf45ae006... | 
				
			||||||
 | 
					snekstack/create_stack               [ OK    ] [ 0.00000700 / 0.00000600 CPU ] | 
				
			||||||
 | 
					snekstack/push_stack                 [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					snekstack/pop_stack                  [ OK    ] [ 0.00000700 / 0.00000700 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xf83a103b... | 
				
			||||||
 | 
					snekstack/heterogenous_stack         [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					1 of 1 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x53a94d13... | 
				
			||||||
 | 
					snekstack/multiple_types_stack       [ OK    ] [ 0.00000800 / 0.00000800 CPU ] | 
				
			||||||
 | 
					1 of 1 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xd977a296... | 
				
			||||||
 | 
					object-integer-def/integer_constant  [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					object-integer-def/integer_obj       [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x9850a5b5... | 
				
			||||||
 | 
					object-integer/positive              [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					object-integer/zero                  [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					object-integer/negative              [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x06edb0c3... | 
				
			||||||
 | 
					object-float/positive                [ OK    ] [ 0.00000600 / 0.00000400 CPU ] | 
				
			||||||
 | 
					object-float/zero                    [ OK    ] [ 0.00002200 / 0.00001700 CPU ] | 
				
			||||||
 | 
					object-float/negative                [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x846fed7d... | 
				
			||||||
 | 
					object-string/copies_value           [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					1 of 1 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x53cf4c00... | 
				
			||||||
 | 
					object-vector/returns_null           [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					object-vector/multiple_objects       [ OK    ] [ 0.00000700 / 0.00000700 CPU ] | 
				
			||||||
 | 
					object-vector/same_object            [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x58fd8016... | 
				
			||||||
 | 
					object-array/empty                   [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					object-array/calloc                  [ OK    ] [ 0.00000300 / 0.00000400 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x7f5412f2... | 
				
			||||||
 | 
					object-array/set_and_get             [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					object-array/set_outside             [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					object-array/get_outside             [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xa5a5383d... | 
				
			||||||
 | 
					object-length/integer                [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					object-length/float                  [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					object-length/string                 [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					object-length/vector                 [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					object-length/array                  [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					5 of 5 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x2e6f75bf... | 
				
			||||||
 | 
					/example/compare                     [ OK    ] [ 0.00000600 / 0.00000400 CPU ] | 
				
			||||||
 | 
					/example/rand                        [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					/example/parameters | 
				
			||||||
 | 
					  foo=one, bar=red                   [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=green                 [ OK    ] [ 0.00000500 / 0.00000600 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=blue                  [ OK    ] [ 0.00000900 / 0.00000800 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=red                   [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=green                 [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=blue                  [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=red                 [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=green               [ OK    ] [ 0.00000300 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=blue                [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					11 of 11 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xdf462866... | 
				
			||||||
 | 
					refcounttest_int_has_refcount        [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					refcounttest_float_has_refcount      [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x3b906f5c... | 
				
			||||||
 | 
					refcount/test_inc_refcount           [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					refcount/test_inc_refcount_more      [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					refcount/test_null_obj               [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x6b51ea68... | 
				
			||||||
 | 
					refcount/has_refcount                [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					refcount/inc_refcount                [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					refcount/dec_refcount                [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/free_refcount               [ OK    ] [ 0.00000400 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/string_freed                [ OK    ] [ 0.00000500 / 0.00000600 CPU ] | 
				
			||||||
 | 
					5 of 5 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xfcdf2928... | 
				
			||||||
 | 
					refcount/has_refcount                [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/inc_refcount                [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/dec_refcount                [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/free_refcount               [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					refcount/string_freed                [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					refcount/vector3                     [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					refcount/vector3-same                [ OK    ] [ 0.00000300 / 0.00000200 CPU ] | 
				
			||||||
 | 
					7 of 7 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x2df34e21... | 
				
			||||||
 | 
					refcount/array_set                   [ OK    ] [ 0.00000800 / 0.00000800 CPU ] | 
				
			||||||
 | 
					refcount/array_free                  [ OK    ] [ 0.00000600 / 0.00000700 CPU ] | 
				
			||||||
 | 
					refcount/has_refcount                [ OK    ] [ 0.00000300 / 0.00000300 CPU ] | 
				
			||||||
 | 
					refcount/inc_refcount                [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					refcount/dec_refcount                [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					refcount/free_refcount               [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/string_freed                [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					refcount/vector3                     [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					8 of 8 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x91892c1e... | 
				
			||||||
 | 
					/example/compare                     [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					/example/rand                        [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					/example/parameters | 
				
			||||||
 | 
					  foo=one, bar=red                   [ OK    ] [ 0.00000500 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=green                 [ OK    ] [ 0.00000500 / 0.00000500 CPU ] | 
				
			||||||
 | 
					  foo=one, bar=blue                  [ OK    ] [ 0.00001100 / 0.00001200 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=red                   [ OK    ] [ 0.00000500 / 0.00000600 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=green                 [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					  foo=two, bar=blue                  [ OK    ] [ 0.00000300 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=red                 [ OK    ] [ 0.00000300 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=green               [ OK    ] [ 0.00000400 / 0.00000400 CPU ] | 
				
			||||||
 | 
					  foo=three, bar=blue                [ OK    ] [ 0.00000400 / 0.00000300 CPU ] | 
				
			||||||
 | 
					11 of 11 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x0dddaf2c... | 
				
			||||||
 | 
					refcount/correctly_free              [ OK    ] [ 0.00000700 / 0.00000700 CPU ] | 
				
			||||||
 | 
					1 of 1 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x435b0c66... | 
				
			||||||
 | 
					mark-and-sweep/vm                    [ OK    ] [ 0.00000600 / 0.00000700 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/vm                    [ OK    ] [ 0.00001400 / 0.00000700 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x85af19f7... | 
				
			||||||
 | 
					mark-and-sweep/test_vm_new           [ OK    ] [ 0.00000800 / 0.00000700 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_vm_new_frame     [ OK    ] [ 0.00000700 / 0.00000600 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_frames_are_freed [ OK    ] [ 0.00000600 / 0.00000600 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x1cceaa41... | 
				
			||||||
 | 
					mark-and-sweep/test_vm_new           [ OK    ] [ 0.00000800 / 0.00000700 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_frames_are_freed [ OK    ] [ 0.00000700 / 0.00000700 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_new_object       [ OK    ] [ 0.00000700 / 0.00000600 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xc169d14b... | 
				
			||||||
 | 
					mark-and-sweep/test_reference_object [ OK    ] [ 0.00000700 / 0.00000700 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_frames_are_freed [ OK    ] [ 0.00000700 / 0.00000700 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xac37539a... | 
				
			||||||
 | 
					mark-and-sweep/test_one_ref          [ OK    ] [ 0.00000900 / 0.00000900 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_multi_ref        [ OK    ] [ 0.00000800 / 0.00000800 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0xaa6df145... | 
				
			||||||
 | 
					mark-and-sweep/test_field_exists     [ OK    ] [ 0.00000900 / 0.00000800 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_marked_is_false  [ OK    ] [ 0.00000600 / 0.00000500 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x22d87982... | 
				
			||||||
 | 
					mark-and-sweep/test_single_frame     [ OK    ] [ 0.00000900 / 0.00000900 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_multi_frame      [ OK    ] [ 0.00001000 / 0.00001100 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x147d09b4... | 
				
			||||||
 | 
					mark-and-sweep/test_trace_vector     [ OK    ] [ 0.00000900 / 0.00000900 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_trace_array      [ OK    ] [ 0.00001200 / 0.00001300 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_trace_nested     [ OK    ] [ 0.00001700 / 0.00001700 CPU ] | 
				
			||||||
 | 
					3 of 3 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					Running test suite with seed 0x93c96b1a... | 
				
			||||||
 | 
					mark-and-sweep/test_simple           [ OK    ] [ 0.00000900 / 0.00000800 CPU ] | 
				
			||||||
 | 
					mark-and-sweep/test_full             [ OK    ] [ 0.00001900 / 0.00002000 CPU ] | 
				
			||||||
 | 
					2 of 2 (100%) tests successful, 0 (0%) test skipped. | 
				
			||||||
 | 
					[100%] Built target run | 
				
			||||||
 | 
					#+END_SRC | 
				
			||||||
| 
		 After Width: | Height: | Size: 311 KiB  | 
@ -0,0 +1,20 @@ | 
				
			|||||||
 | 
					#include <stdio.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int *allocate_scalar_array(int size, int multiplier) { | 
				
			||||||
 | 
						int *array = (int *)malloc(size * sizeof(int)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// On macOS malloc will almost never return a NULL pointer due to
 | 
				
			||||||
 | 
						// virtual memory overcommit, so check for the size as well
 | 
				
			||||||
 | 
						if (array == NULL || size == 1024 * 1024 * 100) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < size; i++) { | 
				
			||||||
 | 
							array[i] = i * multiplier; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return array; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1 @@ | 
				
			|||||||
 | 
					int *allocate_scalar_array(int size, int multiplier); | 
				
			||||||
@ -0,0 +1,57 @@ | 
				
			|||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_allocate_scalar_array_size, { | 
				
			||||||
 | 
						int size = 5; | 
				
			||||||
 | 
						int multiplier = 2; | 
				
			||||||
 | 
						int *result = allocate_scalar_array(size, multiplier); | 
				
			||||||
 | 
						munit_assert_not_null(result, "Function should return a non-null pointer"); | 
				
			||||||
 | 
						free(result); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_allocate_scalar_array_values, { | 
				
			||||||
 | 
						int size = 5; | 
				
			||||||
 | 
						int multiplier = 2; | 
				
			||||||
 | 
						int *result = allocate_scalar_array(size, multiplier); | 
				
			||||||
 | 
						int expected[5]; | 
				
			||||||
 | 
						expected[0] = 0; | 
				
			||||||
 | 
						expected[1] = 2; | 
				
			||||||
 | 
						expected[2] = 4; | 
				
			||||||
 | 
						expected[3] = 6; | 
				
			||||||
 | 
						expected[4] = 8; | 
				
			||||||
 | 
						for (int i = 0; i < size; i++) { | 
				
			||||||
 | 
							munit_assert_int(result[i], ==, expected[i], "Element does not match expected value"); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						free(result); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_allocate_scalar_array_zero_multiplier, { | 
				
			||||||
 | 
						int size = 3; | 
				
			||||||
 | 
						int multiplier = 0; | 
				
			||||||
 | 
						int *result = allocate_scalar_array(size, multiplier); | 
				
			||||||
 | 
						for (int i = 0; i < size; i++) { | 
				
			||||||
 | 
							munit_assert_int(result[i], ==, 0, "All elements should be 0 with multiplier 0"); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						free(result); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_allocate_too_much, { | 
				
			||||||
 | 
						int size = 1024 * 1024 * 100; | 
				
			||||||
 | 
						int multiplier = 1; | 
				
			||||||
 | 
						int *result = allocate_scalar_array(size, multiplier); | 
				
			||||||
 | 
						munit_assert_null(result, "Giant allocation should result in NULL"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/test_allocate_scalar_array_size", test_allocate_scalar_array_size), | 
				
			||||||
 | 
							munit_test("/test_allocate_scalar_array_values", test_allocate_scalar_array_values), | 
				
			||||||
 | 
							munit_test("/test_allocate_scalar_array_zero_multiplier", test_allocate_scalar_array_zero_multiplier), | 
				
			||||||
 | 
							munit_test("/test_allocate_too_much", test_allocate_too_much), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("allocate_scalar_array", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,13 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int *allocate_scalar_list(int size, int multiplier) { | 
				
			||||||
 | 
						int *lst = (int *)malloc(size * sizeof(int)); | 
				
			||||||
 | 
						if (lst == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						for (int i = 0; i < size; i++) { | 
				
			||||||
 | 
							lst[i] = i * multiplier; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						return lst; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1 @@ | 
				
			|||||||
 | 
					int *allocate_scalar_list(int size, int multiplier); | 
				
			||||||
@ -0,0 +1,21 @@ | 
				
			|||||||
 | 
					#include <stdio.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						const int num_lists = 500; | 
				
			||||||
 | 
						for (int i = 0; i < num_lists; i++) { | 
				
			||||||
 | 
							int *lst = allocate_scalar_list(50000, 2); | 
				
			||||||
 | 
							if (lst == NULL) { | 
				
			||||||
 | 
								printf("Failed to allocate list\n"); | 
				
			||||||
 | 
								return 1; | 
				
			||||||
 | 
							} else { | 
				
			||||||
 | 
								// printf("Allocated list %d\n", i);
 | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							free(lst); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("Allocated %d lists\n", num_lists); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,5 @@ | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					// Q: In a little-endian system, how would the hexadecimal number
 | 
				
			||||||
 | 
					// 0xA1B2C3D4 be stored in memory?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A: 0xD4, 0xC3, 0xB2, 0xA1
 | 
				
			||||||
@ -0,0 +1,8 @@ | 
				
			|||||||
 | 
					#include "stdlib.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					void allocate_int(int **pointer_pointer, int value) { | 
				
			||||||
 | 
						int *number = (int *)malloc(sizeof(int)); | 
				
			||||||
 | 
						*pointer_pointer = number; | 
				
			||||||
 | 
						**pointer_pointer = value; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,4 @@ | 
				
			|||||||
 | 
					#include <stdio.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void allocate_int(int **pointer_pointer, int value); | 
				
			||||||
@ -0,0 +1,39 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_allocate, { | 
				
			||||||
 | 
						int *pointer = NULL; | 
				
			||||||
 | 
						allocate_int(&pointer, 10); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_ptr_not_null(pointer, "Should allocate pointer"); | 
				
			||||||
 | 
						assert_int(*pointer, ==, 10, "Should assign value to pointer"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(pointer); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_does_not_overwrite, { | 
				
			||||||
 | 
						int value = 5; | 
				
			||||||
 | 
						int *pointer = &value; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allocate_int(&pointer, 20); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(value, ==, 5, "Should not overwrite original value"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_ptr_not_null(pointer, "Should allocate pointer"); | 
				
			||||||
 | 
						assert_int(*pointer, ==, 20, "Should assign value to pointer"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(pointer); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/create", test_allocate), | 
				
			||||||
 | 
							munit_test("/overwrite", test_does_not_overwrite), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("allocate_list", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,20 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					token_t** create_token_pointer_array(token_t* tokens, size_t count) { | 
				
			||||||
 | 
						token_t** token_pointers = malloc(count * sizeof(token_t*)); | 
				
			||||||
 | 
						if (token_pointers == NULL) { | 
				
			||||||
 | 
							exit(1); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (size_t i = 0; i < count; ++i) { | 
				
			||||||
 | 
							token_t *token_pointer = (token_t *)malloc(sizeof(token_t)); | 
				
			||||||
 | 
							token_pointers[i] = token_pointer; | 
				
			||||||
 | 
							token_pointers[i]->literal = tokens[i].literal; | 
				
			||||||
 | 
							token_pointers[i]->column = tokens[i].column; | 
				
			||||||
 | 
							token_pointers[i]->line = tokens[i].line; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						return token_pointers; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,7 @@ | 
				
			|||||||
 | 
					typedef struct Token { | 
				
			||||||
 | 
						char* literal; | 
				
			||||||
 | 
						int line; | 
				
			||||||
 | 
						int column; | 
				
			||||||
 | 
					} token_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					token_t** create_token_pointer_array(token_t* tokens, size_t count); | 
				
			||||||
@ -0,0 +1,77 @@ | 
				
			|||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_create_token_pointer_array_single, | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						token_t token = {"hello", 1, 1}; | 
				
			||||||
 | 
						token_t** result = create_token_pointer_array(&token, 1); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						munit_assert_not_null(result, "Result array should not be null"); | 
				
			||||||
 | 
						munit_assert_not_null(result[0], "First token pointer should not be null"); | 
				
			||||||
 | 
						munit_assert_string_equal(result[0]->literal, "hello", "Literal should match"); | 
				
			||||||
 | 
						munit_assert_int(result[0]->line, ==, 1, "Line number should match"); | 
				
			||||||
 | 
						munit_assert_int(result[0]->column, ==, 1, "Column number should match"); | 
				
			||||||
 | 
						munit_assert_ptr_not_equal(result[0], &token, "Token pointer should not point to original token"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(result[0]); | 
				
			||||||
 | 
						free(result); | 
				
			||||||
 | 
					}) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_create_token_pointer_array_multiple, | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						token_t tokens[3] = { | 
				
			||||||
 | 
							{"foo", 1, 1}, | 
				
			||||||
 | 
							{"bar", 2, 5}, | 
				
			||||||
 | 
							{"baz", 3, 10} | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
						token_t** result = create_token_pointer_array(tokens, 3); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						munit_assert_not_null(result, "Result array should not be null"); | 
				
			||||||
 | 
						for (int i = 0; i < 3; i++) { | 
				
			||||||
 | 
							munit_assert_not_null(result[i], "Token pointer should not be null"); | 
				
			||||||
 | 
							munit_assert_string_equal(result[i]->literal, tokens[i].literal, "Literal should match"); | 
				
			||||||
 | 
							munit_assert_int(result[i]->line, ==, tokens[i].line, "Line number should match"); | 
				
			||||||
 | 
							munit_assert_int(result[i]->column, ==, tokens[i].column, "Column number should match"); | 
				
			||||||
 | 
							munit_assert_ptr_not_equal(result[i], &tokens[i], "Token pointer should not point to original token"); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < 3; i++) { | 
				
			||||||
 | 
							free(result[i]); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						free(result); | 
				
			||||||
 | 
					}) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_create_token_pointer_array_memory_allocation, | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						token_t tokens[2] = { | 
				
			||||||
 | 
							{"test1", 1, 1}, | 
				
			||||||
 | 
							{"test2", 2, 2} | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
						token_t** result = create_token_pointer_array(tokens, 2); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						munit_assert_not_null(result, "Result array should not be null"); | 
				
			||||||
 | 
						munit_assert_not_null(result[0], "First token pointer should not be null"); | 
				
			||||||
 | 
						munit_assert_not_null(result[1], "Second token pointer should not be null"); | 
				
			||||||
 | 
						munit_assert_ptr_not_equal(result[0], result[1], "Token pointers should be different"); | 
				
			||||||
 | 
						munit_assert_ptr_not_equal(result[0], &tokens[0], "First token pointer should not point to original token"); | 
				
			||||||
 | 
						munit_assert_ptr_not_equal(result[1], &tokens[1], "Second token pointer should not point to original token"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(result[0]); | 
				
			||||||
 | 
						free(result[1]); | 
				
			||||||
 | 
						free(result); | 
				
			||||||
 | 
					}) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/test_create_token_pointer_array_single", test_create_token_pointer_array_single), | 
				
			||||||
 | 
							munit_test("/test_create_token_pointer_array_multiple", test_create_token_pointer_array_multiple), | 
				
			||||||
 | 
							munit_test("/test_create_token_pointer_array_memory_allocation", test_create_token_pointer_array_memory_allocation), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("create_token_pointer_array", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,13 @@ | 
				
			|||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void snek_zero_out(void *ptr, snek_object_kind_t kind){ | 
				
			||||||
 | 
						if (kind == INTEGER) { | 
				
			||||||
 | 
							((snek_int_t *)ptr)->value = 0; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						if (kind == FLOAT) { | 
				
			||||||
 | 
							((snek_float_t *)ptr)->value = 0.0; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						if (kind == BOOL) { | 
				
			||||||
 | 
							((snek_bool_t *)ptr)->value = 0; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,22 @@ | 
				
			|||||||
 | 
					typedef enum SnekObjectKind { | 
				
			||||||
 | 
						INTEGER, | 
				
			||||||
 | 
						FLOAT, | 
				
			||||||
 | 
						BOOL, | 
				
			||||||
 | 
					} snek_object_kind_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct SnekInt { | 
				
			||||||
 | 
						char *name; | 
				
			||||||
 | 
						int value; | 
				
			||||||
 | 
					} snek_int_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct SnekFloat { | 
				
			||||||
 | 
						char *name; | 
				
			||||||
 | 
						float value; | 
				
			||||||
 | 
					} snek_float_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct SnekBool { | 
				
			||||||
 | 
						char *name; | 
				
			||||||
 | 
						unsigned int value; | 
				
			||||||
 | 
					} snek_bool_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void snek_zero_out(void *ptr, snek_object_kind_t kind); | 
				
			||||||
@ -0,0 +1,55 @@ | 
				
			|||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_zero_out_integer, { | 
				
			||||||
 | 
						snek_int_t integer; | 
				
			||||||
 | 
						integer.value = 42; | 
				
			||||||
 | 
						snek_zero_out(&integer, INTEGER); | 
				
			||||||
 | 
						munit_assert_int(integer.value, ==, 0, "Integer should be zeroed out to 0"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_zero_out_float, { | 
				
			||||||
 | 
						snek_float_t float_num; | 
				
			||||||
 | 
						float_num.value = 3.14; | 
				
			||||||
 | 
						snek_zero_out(&float_num, FLOAT); | 
				
			||||||
 | 
						munit_assert_float(float_num.value, ==, 0.0, "Float should be zeroed out to 0.0"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_zero_out_bool, { | 
				
			||||||
 | 
						snek_bool_t boolean; | 
				
			||||||
 | 
						boolean.value = 1; | 
				
			||||||
 | 
						snek_zero_out(&boolean, BOOL); | 
				
			||||||
 | 
						munit_assert_int(boolean.value, ==, 0, "Boolean should be zeroed out to 0"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_zero_out_nonzero_values, { | 
				
			||||||
 | 
						snek_int_t integer; | 
				
			||||||
 | 
						snek_float_t float_num; | 
				
			||||||
 | 
						snek_bool_t boolean; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						integer.value = -100; | 
				
			||||||
 | 
						float_num.value = -99.99; | 
				
			||||||
 | 
						boolean.value = 255; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snek_zero_out(&integer, INTEGER); | 
				
			||||||
 | 
						snek_zero_out(&float_num, FLOAT); | 
				
			||||||
 | 
						snek_zero_out(&boolean, BOOL); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						munit_assert_int(integer.value, ==, 0, "Negative integer should be zeroed out to 0"); | 
				
			||||||
 | 
						munit_assert_float(float_num.value, ==, 0.0, "Negative float should be zeroed out to 0.0"); | 
				
			||||||
 | 
						munit_assert_int(boolean.value, ==, 0, "Non-zero boolean should be zeroed out to 0"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/test_zero_out_integer", test_zero_out_integer), | 
				
			||||||
 | 
							munit_test("/test_zero_out_float", test_zero_out_float), | 
				
			||||||
 | 
							munit_test("/test_zero_out_bool", test_zero_out_bool), | 
				
			||||||
 | 
							munit_test("/test_zero_out_nonzero_values", test_zero_out_nonzero_values), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snek_zero_out", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,16 @@ | 
				
			|||||||
 | 
					void swap_ints(int *a, int *b) { | 
				
			||||||
 | 
						if (a == b) return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Either:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int tmp = *a; | 
				
			||||||
 | 
						*a = *b; | 
				
			||||||
 | 
						*b = tmp; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Or:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Below works, but is kind of a meme answer
 | 
				
			||||||
 | 
						// *a ^= *b;
 | 
				
			||||||
 | 
						// *b ^= *a;
 | 
				
			||||||
 | 
						// *a ^= *b;
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1 @@ | 
				
			|||||||
 | 
					void swap_ints(int *a, int *b); | 
				
			||||||
@ -0,0 +1,35 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdio.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_swap_ints, { | 
				
			||||||
 | 
						int a = 5; | 
				
			||||||
 | 
						int b = 6; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap_ints(&a, &b); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(a, ==, 6, "a is now 6"); | 
				
			||||||
 | 
						assert_int(b, ==, 5, "b is now 5"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_swap_ints_same, { | 
				
			||||||
 | 
						int a = 5; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap_ints(&a, &a); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(a, ==, 5, "a is still 5"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/swap_ints", test_swap_ints), | 
				
			||||||
 | 
							munit_test("/swap_ints_same", test_swap_ints_same), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("void-pointer", tests); | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,7 @@ | 
				
			|||||||
 | 
					void swap_strings(char **a, char **b) { | 
				
			||||||
 | 
						if (a == b) return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *tmp = *a; | 
				
			||||||
 | 
						*a = *b; | 
				
			||||||
 | 
						*b = tmp; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1 @@ | 
				
			|||||||
 | 
					void swap_strings(char **a, char **b); | 
				
			||||||
@ -0,0 +1,37 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdio.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_swap_str, { | 
				
			||||||
 | 
						char *a = "Hello"; | 
				
			||||||
 | 
						char *b = "Goodbye"; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap_strings(&a, &b); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_string_equal(a, "Goodbye", "a is now 'Goodbye'"); | 
				
			||||||
 | 
						assert_string_equal(b, "Hello", "b is now 'Hello'"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_swap_str_long, { | 
				
			||||||
 | 
						char *a = "terminal.shop"; | 
				
			||||||
 | 
						char *b = "ssh"; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap_strings(&a, &b); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_string_equal(a, "ssh", "a is now 'ssh'"); | 
				
			||||||
 | 
						assert_string_equal(b, "terminal.shop", "b is now 'terminal.shop'"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/swap_str", test_swap_str), | 
				
			||||||
 | 
							munit_test("/test_swap_str_long", test_swap_str_long), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("void-pointer", tests); | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,15 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void swap(void *vp1, void *vp2, size_t size) { | 
				
			||||||
 | 
						if (vp1 == vp2) return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void *tmp = boot_malloc(size); | 
				
			||||||
 | 
						if (tmp == NULL) return; | 
				
			||||||
 | 
						memcpy(tmp, vp1, size); | 
				
			||||||
 | 
						memcpy(vp1, vp2, size); | 
				
			||||||
 | 
						memcpy(vp2, tmp, size); | 
				
			||||||
 | 
						boot_free(tmp); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,3 @@ | 
				
			|||||||
 | 
					#include <stdio.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void swap(void *vp1, void *vp2, size_t size); | 
				
			||||||
@ -0,0 +1,60 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					#include <stdint.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct CoffeeShop { | 
				
			||||||
 | 
						uint64_t quality; | 
				
			||||||
 | 
						uint64_t taste; | 
				
			||||||
 | 
						uint64_t branding; | 
				
			||||||
 | 
					} coffee_shop_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_generic_ints, { | 
				
			||||||
 | 
						int i1 = 1234; | 
				
			||||||
 | 
						int i2 = 5678; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap(&i1, &i2, sizeof(int)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(i1, ==, 5678, "i1 should be i2's original value"); | 
				
			||||||
 | 
						assert_int(i2, ==, 1234, "i2 should be i1's original value"); | 
				
			||||||
 | 
						assert_true(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_generic_strings, { | 
				
			||||||
 | 
						char *s1 = "dax"; | 
				
			||||||
 | 
						char *s2 = "adam"; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap(&s1, &s2, sizeof(char *)); | 
				
			||||||
 | 
						assert_string_equal(s1, "adam", "s1 should be s2's original value"); | 
				
			||||||
 | 
						assert_string_equal(s2, "dax", "s2 should be s1's original value"); | 
				
			||||||
 | 
						assert_true(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_generic_structs, { | 
				
			||||||
 | 
						coffee_shop_t sbucks = {2, 3, 4}; | 
				
			||||||
 | 
						coffee_shop_t terminalshop = {10, 10, 10}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						swap(&sbucks, &terminalshop, sizeof(coffee_shop_t)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(sbucks.quality, ==, 10, "sbucks.quality should be terminalshop.quality"); | 
				
			||||||
 | 
						assert_int(sbucks.taste, ==, 10, "sbucks.taste should be terminalshop.taste"); | 
				
			||||||
 | 
						assert_int(sbucks.branding, ==, 10, "sbucks.branding should be terminalshop.branding"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(terminalshop.quality, ==, 2, "terminalshop.quality should be sbucks.quality"); | 
				
			||||||
 | 
						assert_int(terminalshop.taste, ==, 3, "terminalshop.taste should be sbucks.taste"); | 
				
			||||||
 | 
						assert_int(terminalshop.branding, ==, 4, "terminalshop.branding should be sbucks.branding"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/generic_ints", test_generic_ints), | 
				
			||||||
 | 
							munit_test("/generic_strings", test_generic_strings), | 
				
			||||||
 | 
							munit_test("/generic_struct", test_generic_structs), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("swap", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,39 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, create_stack_small, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(3); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 3, "Sets capacity to 3"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, create_stack_large, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(100); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 100, "Sets capacity to 100"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/create_stack_small", create_stack_small), | 
				
			||||||
 | 
							munit_test("/create_stack_large", create_stack_large), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snekstack", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,19 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						my_stack_t *stack = (my_stack_t *)boot_malloc(sizeof(my_stack_t)); | 
				
			||||||
 | 
						if (stack == NULL) return NULL; | 
				
			||||||
 | 
						stack->count = 0; | 
				
			||||||
 | 
						stack->capacity = capacity; | 
				
			||||||
 | 
						stack->data = boot_malloc(sizeof(void*) * capacity); | 
				
			||||||
 | 
						if (stack->data == NULL) { | 
				
			||||||
 | 
							boot_free(stack); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stack; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,9 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct Stack { | 
				
			||||||
 | 
						size_t count; | 
				
			||||||
 | 
						size_t capacity; | 
				
			||||||
 | 
						void **data; | 
				
			||||||
 | 
					} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity); | 
				
			||||||
@ -0,0 +1,88 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, create_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(10); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 10, "Sets capacity to 10"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, push_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int a = 1; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "2 elements in the stack"); | 
				
			||||||
 | 
						assert_ptr_equal(s->data[0], &a, "element inserted into stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, push_double_capacity, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int a = 1; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "2 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 4, "Capacity is doubled"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 3, "3 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should reallocate memory.
 | 
				
			||||||
 | 
						assert_int_equal(boot_realloc_count(), 1, "Must reallocate memory for stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/create_stack", create_stack), | 
				
			||||||
 | 
							munit_test("/push_stack", push_stack), | 
				
			||||||
 | 
							munit_test("/push_double_capacity", push_double_capacity), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snekstack", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,39 @@ | 
				
			|||||||
 | 
					#include <assert.h> | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (stack->count >= stack->capacity) { | 
				
			||||||
 | 
							void **data = boot_realloc(stack->data, sizeof(void *) * stack->capacity * 2); | 
				
			||||||
 | 
							if (data == NULL) return; | 
				
			||||||
 | 
							stack->data = data; | 
				
			||||||
 | 
							stack->capacity *= 2; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->data[stack->count] = obj; | 
				
			||||||
 | 
						stack->count++; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// don't touch below this line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity) { | 
				
			||||||
 | 
						my_stack_t *stack = boot_malloc(sizeof(my_stack_t)); | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count = 0; | 
				
			||||||
 | 
						stack->capacity = capacity; | 
				
			||||||
 | 
						stack->data = boot_malloc(stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
						if (stack->data == NULL) { | 
				
			||||||
 | 
							boot_free(stack); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stack; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,10 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct Stack { | 
				
			||||||
 | 
						size_t count; | 
				
			||||||
 | 
						size_t capacity; | 
				
			||||||
 | 
						void **data; | 
				
			||||||
 | 
					} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity); | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj); | 
				
			||||||
@ -0,0 +1,121 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, pop_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int one = 1; | 
				
			||||||
 | 
						int two = 2; | 
				
			||||||
 | 
						int three = 3; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &one); | 
				
			||||||
 | 
						stack_push(s, &two); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "2 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &three); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 4, "Capacity is doubled"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 3, "3 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int *popped = stack_pop(s); | 
				
			||||||
 | 
						assert_int(*popped, ==, three, "Should pop the last element"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						popped = stack_pop(s); | 
				
			||||||
 | 
						assert_int(*popped, ==, two, "Should pop the last element"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						popped = stack_pop(s); | 
				
			||||||
 | 
						assert_int(*popped, ==, one, "Should pop the only remaining element"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						popped = stack_pop(s); | 
				
			||||||
 | 
						assert_null(popped, "No remaining elements"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, pop_stack_empty, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int *popped = stack_pop(s); | 
				
			||||||
 | 
						assert_null(popped, "Should return null when popping an empty stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, push_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int a = 1; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "2 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 4, "Capacity is doubled"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 3, "3 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, create_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(10); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 10, "Sets capacity to 10"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up our allocated data.
 | 
				
			||||||
 | 
						boot_free(s->data); | 
				
			||||||
 | 
						boot_free(s); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should be nothing left that is allocated.
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/create_stack", create_stack), | 
				
			||||||
 | 
							munit_test("/push_stack", push_stack), | 
				
			||||||
 | 
							munit_test("/pop_stack", pop_stack), | 
				
			||||||
 | 
							munit_test("/pop_stack_empty", pop_stack_empty), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snekstack", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,47 @@ | 
				
			|||||||
 | 
					#include <assert.h> | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack->count == 0) return NULL; | 
				
			||||||
 | 
						stack->count--; | 
				
			||||||
 | 
						return stack->data[stack->count]; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// don't touch below this line'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj) { | 
				
			||||||
 | 
						if (stack->count == stack->capacity) { | 
				
			||||||
 | 
							stack->capacity *= 2; | 
				
			||||||
 | 
							void **temp = boot_realloc(stack->data, stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
							if (temp == NULL) { | 
				
			||||||
 | 
								stack->capacity /= 2; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								exit(1); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							stack->data = temp; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						stack->data[stack->count] = obj; | 
				
			||||||
 | 
						stack->count++; | 
				
			||||||
 | 
						return; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity) { | 
				
			||||||
 | 
						my_stack_t *stack = boot_malloc(sizeof(my_stack_t)); | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count = 0; | 
				
			||||||
 | 
						stack->capacity = capacity; | 
				
			||||||
 | 
						stack->data = boot_malloc(stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
						if (stack->data == NULL) { | 
				
			||||||
 | 
							boot_free(stack); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stack; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,11 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct Stack { | 
				
			||||||
 | 
						size_t count; | 
				
			||||||
 | 
						size_t capacity; | 
				
			||||||
 | 
						void **data; | 
				
			||||||
 | 
					} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity); | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj); | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack); | 
				
			||||||
@ -0,0 +1,88 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, pop_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int one = 1; | 
				
			||||||
 | 
						int two = 2; | 
				
			||||||
 | 
						int three = 3; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &one); | 
				
			||||||
 | 
						stack_push(s, &two); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "2 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &three); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 4, "Capacity is doubled"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 3, "3 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int *popped = stack_pop(s); | 
				
			||||||
 | 
						assert_int(*popped, ==, three, "Should pop the last element"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						popped = stack_pop(s); | 
				
			||||||
 | 
						assert_int(*popped, ==, two, "Should pop the last element"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						popped = stack_pop(s); | 
				
			||||||
 | 
						assert_int(*popped, ==, one, "Should pop the only remaining element"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						popped = stack_pop(s); | 
				
			||||||
 | 
						assert_null(popped, "No remaining elements"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_free(s); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, push_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int a = 1; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 2, "Sets capacity to 2"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "2 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, &a); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 4, "Capacity is doubled"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 3, "3 elements in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_free(s); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, create_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(10); | 
				
			||||||
 | 
						assert_int(s->capacity, ==, 10, "Sets capacity to 10"); | 
				
			||||||
 | 
						assert_int(s->count, ==, 0, "No elements in the stack yet"); | 
				
			||||||
 | 
						assert_ptr_not_null(s->data, "Allocates the stack data"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_free(s); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/create_stack", create_stack), | 
				
			||||||
 | 
							munit_test("/push_stack", push_stack), | 
				
			||||||
 | 
							munit_test("/pop_stack", pop_stack), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snekstack", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,60 @@ | 
				
			|||||||
 | 
					#include <assert.h> | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_free(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack == NULL) return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (stack->data != NULL) { | 
				
			||||||
 | 
							boot_free(stack->data); | 
				
			||||||
 | 
							stack->data = NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(stack); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// don't touch below this line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack->count == 0) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count--; | 
				
			||||||
 | 
						return stack->data[stack->count]; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj) { | 
				
			||||||
 | 
						if (stack->count == stack->capacity) { | 
				
			||||||
 | 
							stack->capacity *= 2; | 
				
			||||||
 | 
							void **temp = boot_realloc(stack->data, stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
							if (temp == NULL) { | 
				
			||||||
 | 
								stack->capacity /= 2; | 
				
			||||||
 | 
								exit(1); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							stack->data = temp; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						stack->data[stack->count] = obj; | 
				
			||||||
 | 
						stack->count++; | 
				
			||||||
 | 
						return; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity) { | 
				
			||||||
 | 
						my_stack_t *stack = boot_malloc(sizeof(my_stack_t)); | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count = 0; | 
				
			||||||
 | 
						stack->capacity = capacity; | 
				
			||||||
 | 
						stack->data = boot_malloc(stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
						if (stack->data == NULL) { | 
				
			||||||
 | 
							boot_free(stack); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stack; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,12 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct Stack { | 
				
			||||||
 | 
						size_t count; | 
				
			||||||
 | 
						size_t capacity; | 
				
			||||||
 | 
						void **data; | 
				
			||||||
 | 
					} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity); | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj); | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack); | 
				
			||||||
 | 
					void stack_free(my_stack_t *stack); | 
				
			||||||
@ -0,0 +1,10 @@ | 
				
			|||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					#include "stdlib.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void scary_double_push(my_stack_t *s) { | 
				
			||||||
 | 
						stack_push(s, (void *)1337); | 
				
			||||||
 | 
						int *number = malloc(sizeof(int)); | 
				
			||||||
 | 
						if (number == NULL) return; | 
				
			||||||
 | 
						*number = 1024; | 
				
			||||||
 | 
						stack_push(s, number); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,3 @@ | 
				
			|||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void scary_double_push(my_stack_t *s); | 
				
			||||||
@ -0,0 +1,33 @@ | 
				
			|||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// #include "bootlib.h"
 | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, heterogenous_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(2); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scary_double_push(s); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "Should have two items in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int value = (int)s->data[0]; | 
				
			||||||
 | 
						assert_int(value, ==, 1337, "Zero item should be 1337"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int *pointer = s->data[1]; | 
				
			||||||
 | 
						assert_int(*pointer, ==, 1024, "Top item should be 1024"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(pointer); | 
				
			||||||
 | 
						stack_free(s); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/heterogenous_stack", heterogenous_stack), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snekstack", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,58 @@ | 
				
			|||||||
 | 
					#include <assert.h> | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_free(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (stack->data != NULL) { | 
				
			||||||
 | 
							free(stack->data); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(stack); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack->count == 0) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count--; | 
				
			||||||
 | 
						return stack->data[stack->count]; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj) { | 
				
			||||||
 | 
						if (stack->count == stack->capacity) { | 
				
			||||||
 | 
							stack->capacity *= 2; | 
				
			||||||
 | 
							void **temp = realloc(stack->data, stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
							if (temp == NULL) { | 
				
			||||||
 | 
								stack->capacity /= 2; | 
				
			||||||
 | 
								exit(1); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							stack->data = temp; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						stack->data[stack->count] = obj; | 
				
			||||||
 | 
						stack->count++; | 
				
			||||||
 | 
						return; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity) { | 
				
			||||||
 | 
						my_stack_t *stack = malloc(sizeof(my_stack_t)); | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count = 0; | 
				
			||||||
 | 
						stack->capacity = capacity; | 
				
			||||||
 | 
						stack->data = malloc(stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
						if (stack->data == NULL) { | 
				
			||||||
 | 
							free(stack); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stack; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,14 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct Stack { | 
				
			||||||
 | 
						size_t count; | 
				
			||||||
 | 
						size_t capacity; | 
				
			||||||
 | 
						void **data; | 
				
			||||||
 | 
					} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity); | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj); | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack); | 
				
			||||||
 | 
					void stack_free(my_stack_t *stack); | 
				
			||||||
@ -0,0 +1,20 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push_multiple_types(my_stack_t *s) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						float *pi = (float *)malloc(sizeof(float)); | 
				
			||||||
 | 
						if (pi == NULL) return; | 
				
			||||||
 | 
						*pi = 3.14; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, pi); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *text = "Sneklang is blazingly slow!"; | 
				
			||||||
 | 
						char *str = (char *)malloc(sizeof(char) * strlen(text)); | 
				
			||||||
 | 
						if (str == NULL) return; | 
				
			||||||
 | 
						strcpy(str, text); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push(s, str); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,3 @@ | 
				
			|||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push_multiple_types(my_stack_t *s); | 
				
			||||||
@ -0,0 +1,34 @@ | 
				
			|||||||
 | 
					#include "exercise.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// #include "bootlib.h"
 | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, multiple_types_stack, { | 
				
			||||||
 | 
						my_stack_t *s = stack_new(4); | 
				
			||||||
 | 
						assert_ptr_not_null(s, "Must allocate a new stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack_push_multiple_types(s); | 
				
			||||||
 | 
						assert_int(s->count, ==, 2, "Should have two items in the stack"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float *f = s->data[0]; | 
				
			||||||
 | 
						assert_float(*f, ==, 3.14, "Float is equal"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *string = s->data[1]; | 
				
			||||||
 | 
						assert_string_equal(string, "Sneklang is blazingly slow!", "char* is equal"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(f); | 
				
			||||||
 | 
						free(string); | 
				
			||||||
 | 
						stack_free(s); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/multiple_types_stack", multiple_types_stack), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("snekstack", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,58 @@ | 
				
			|||||||
 | 
					#include <assert.h> | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "snekstack.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_free(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (stack->data != NULL) { | 
				
			||||||
 | 
							free(stack->data); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(stack); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack) { | 
				
			||||||
 | 
						if (stack->count == 0) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count--; | 
				
			||||||
 | 
						return stack->data[stack->count]; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj) { | 
				
			||||||
 | 
						if (stack->count == stack->capacity) { | 
				
			||||||
 | 
							stack->capacity *= 2; | 
				
			||||||
 | 
							void **temp = realloc(stack->data, stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
							if (temp == NULL) { | 
				
			||||||
 | 
								stack->capacity /= 2; | 
				
			||||||
 | 
								exit(1); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							stack->data = temp; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						stack->data[stack->count] = obj; | 
				
			||||||
 | 
						stack->count++; | 
				
			||||||
 | 
						return; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity) { | 
				
			||||||
 | 
						my_stack_t *stack = malloc(sizeof(my_stack_t)); | 
				
			||||||
 | 
						if (stack == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stack->count = 0; | 
				
			||||||
 | 
						stack->capacity = capacity; | 
				
			||||||
 | 
						stack->data = malloc(stack->capacity * sizeof(void *)); | 
				
			||||||
 | 
						if (stack->data == NULL) { | 
				
			||||||
 | 
							free(stack); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stack; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,14 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct Stack { | 
				
			||||||
 | 
						size_t count; | 
				
			||||||
 | 
						size_t capacity; | 
				
			||||||
 | 
						void **data; | 
				
			||||||
 | 
					} my_stack_t; // NOTE: renamed due to std naming conflict on macOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my_stack_t *stack_new(size_t capacity); | 
				
			||||||
 | 
					void stack_push(my_stack_t *stack, void *obj); | 
				
			||||||
 | 
					void *stack_pop(my_stack_t *stack); | 
				
			||||||
 | 
					void stack_free(my_stack_t *stack); | 
				
			||||||
@ -0,0 +1,30 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_integer_constant, { | 
				
			||||||
 | 
						assert_int(INTEGER, ==, 0, "INTEGER is defined as 0"); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_integer_obj, { | 
				
			||||||
 | 
						snek_object_t *obj = malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						obj->kind = INTEGER; | 
				
			||||||
 | 
						obj->data.v_int = 0; | 
				
			||||||
 | 
						assert_int(obj->kind, ==, INTEGER, "must be INTEGER type"); | 
				
			||||||
 | 
						assert_int(obj->data.v_int, ==, 0, "must equal zero"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(obj); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/integer_constant", test_integer_constant), | 
				
			||||||
 | 
							munit_test("/integer_obj", test_integer_obj), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("object-integer-def", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,13 @@ | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum SnekObjectKind { | 
				
			||||||
 | 
						INTEGER, | 
				
			||||||
 | 
					} snek_object_kind_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union SnekObjectData { | 
				
			||||||
 | 
						int v_int; | 
				
			||||||
 | 
					} snek_object_data_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct SnekObject { | 
				
			||||||
 | 
						snek_object_kind_t kind; | 
				
			||||||
 | 
						snek_object_data_t data; | 
				
			||||||
 | 
					} snek_object_t; | 
				
			||||||
@ -0,0 +1,40 @@ | 
				
			|||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_positive, { | 
				
			||||||
 | 
						snek_object_t *int_object = new_snek_integer(42); | 
				
			||||||
 | 
						assert_int(int_object->data.v_int, ==, 42, "must allow positive numbers"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(int_object); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_zero, { | 
				
			||||||
 | 
						snek_object_t *int_object = new_snek_integer(0); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(int_object->kind, ==, INTEGER, "must be INTEGER type"); | 
				
			||||||
 | 
						assert_int(int_object->data.v_int, ==, 0, "must equal zero"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(int_object); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_negative, { | 
				
			||||||
 | 
						snek_object_t *int_object = new_snek_integer(-5); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(int_object->kind, ==, INTEGER, "must be INTEGER type"); | 
				
			||||||
 | 
						assert_int(int_object->data.v_int, ==, -5, "must allow negative numbers"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(int_object); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/positive", test_positive), | 
				
			||||||
 | 
							munit_test("/zero", test_zero), | 
				
			||||||
 | 
							munit_test("/negative", test_negative), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("object-integer", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,11 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_integer(int value) { | 
				
			||||||
 | 
						snek_object_t *number = (snek_object_t *)malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (number == NULL) return NULL; | 
				
			||||||
 | 
						number->kind = INTEGER; | 
				
			||||||
 | 
						number->data.v_int = value; | 
				
			||||||
 | 
						return number; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,14 @@ | 
				
			|||||||
 | 
					typedef enum SnekObjectKind { | 
				
			||||||
 | 
						INTEGER, | 
				
			||||||
 | 
					} snek_object_kind_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union SnekObjectData { | 
				
			||||||
 | 
						int v_int; | 
				
			||||||
 | 
					} 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); | 
				
			||||||
@ -0,0 +1,46 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_positive, { | 
				
			||||||
 | 
						snek_object_t *obj = new_snek_float(42); | 
				
			||||||
 | 
						assert_float(obj->data.v_float, ==, 42, "Must accept positive values"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(obj); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_zero, { | 
				
			||||||
 | 
						snek_object_t *obj = new_snek_float(0.0); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT"); | 
				
			||||||
 | 
						assert_float(obj->data.v_float, ==, 0.0, "Must accept 0.0"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(obj); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_negative, { | 
				
			||||||
 | 
						snek_object_t *obj = new_snek_float(-5.0); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT"); | 
				
			||||||
 | 
						assert_float(obj->data.v_float, ==, -5.0, "Must accept negative numbers"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(obj); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/positive", test_positive), | 
				
			||||||
 | 
							munit_test("/zero", test_zero), | 
				
			||||||
 | 
							munit_test("/negative", test_negative), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("object-float", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,25 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_float(float value) { | 
				
			||||||
 | 
						snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) return NULL; | 
				
			||||||
 | 
						obj->kind = FLOAT; | 
				
			||||||
 | 
						obj->data.v_float = value; | 
				
			||||||
 | 
						return obj; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// don't touch below this line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_integer(int value) { | 
				
			||||||
 | 
						snek_object_t *obj = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj->kind = INTEGER; | 
				
			||||||
 | 
						obj->data.v_int = value; | 
				
			||||||
 | 
						return obj; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,17 @@ | 
				
			|||||||
 | 
					typedef enum SnekObjectKind { | 
				
			||||||
 | 
						INTEGER, | 
				
			||||||
 | 
						FLOAT, | 
				
			||||||
 | 
					} snek_object_kind_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union SnekObjectData { | 
				
			||||||
 | 
						int v_int; | 
				
			||||||
 | 
						float v_float; | 
				
			||||||
 | 
					} 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); | 
				
			||||||
@ -0,0 +1,45 @@ | 
				
			|||||||
 | 
					#include <stdbool.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_str_copied, { | 
				
			||||||
 | 
						char *input = "Hello, World!"; | 
				
			||||||
 | 
						snek_object_t *obj = new_snek_string(input); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_int(obj->kind, ==, STRING, "Must be a string!"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should not have pointers be the same, otherwise we didn't copy the value.
 | 
				
			||||||
 | 
						assert_ptr_not_equal( | 
				
			||||||
 | 
							obj->data.v_string, input, "You need to copy the string." | 
				
			||||||
 | 
						); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// But should have the same data!
 | 
				
			||||||
 | 
						//	This way the object can free it's own memory later.
 | 
				
			||||||
 | 
						assert_string_equal( | 
				
			||||||
 | 
							obj->data.v_string, input, "Should copy string correctly" | 
				
			||||||
 | 
						); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Should allocate memory for the string with null terminator.
 | 
				
			||||||
 | 
						bool is_32_bit = sizeof(void *) == 4; | 
				
			||||||
 | 
						int allocated = 14 + (is_32_bit ? 8 : 16); // pointers are larger on x64
 | 
				
			||||||
 | 
						assert_int_equal(boot_alloc_size(), allocated, "Must allocate memory for string"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Free the string, and then free the object.
 | 
				
			||||||
 | 
						boot_free(obj->data.v_string); | 
				
			||||||
 | 
						boot_free(obj); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/copies_value", test_str_copied), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("object-string", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,47 @@ | 
				
			|||||||
 | 
					#include <stddef.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_string(char *value) { | 
				
			||||||
 | 
						snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) return NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t size = strlen(value); | 
				
			||||||
 | 
						char *str = (char *)boot_malloc(sizeof(char) * size + 1); | 
				
			||||||
 | 
						if (str == NULL) { | 
				
			||||||
 | 
							boot_free(obj); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strcpy(str, value); | 
				
			||||||
 | 
						obj->kind = STRING; | 
				
			||||||
 | 
						obj->data.v_string = str; | 
				
			||||||
 | 
						return obj; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// don't touch below this line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_integer(int value) { | 
				
			||||||
 | 
						snek_object_t *obj = boot_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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj->kind = FLOAT; | 
				
			||||||
 | 
						obj->data.v_float = value; | 
				
			||||||
 | 
						return obj; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,20 @@ | 
				
			|||||||
 | 
					typedef enum SnekObjectKind { | 
				
			||||||
 | 
						INTEGER, | 
				
			||||||
 | 
						FLOAT, | 
				
			||||||
 | 
						STRING, | 
				
			||||||
 | 
					} snek_object_kind_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union SnekObjectData { | 
				
			||||||
 | 
						int v_int; | 
				
			||||||
 | 
						float v_float; | 
				
			||||||
 | 
						char* v_string; | 
				
			||||||
 | 
					} 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); | 
				
			||||||
@ -0,0 +1,82 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "munit.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_returns_null, { | 
				
			||||||
 | 
						snek_object_t *vec = new_snek_vector3(NULL, NULL, NULL); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_null(vec, "Should return null when input is null"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(RUN, test_vec_multiple_objects, { | 
				
			||||||
 | 
						snek_object_t *x = new_snek_integer(1); | 
				
			||||||
 | 
						snek_object_t *y = new_snek_integer(2); | 
				
			||||||
 | 
						snek_object_t *z = new_snek_integer(3); | 
				
			||||||
 | 
						snek_object_t *vec = new_snek_vector3(x, y, z); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_ptr_not_null(vec, "should allocate a new object"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Vectors should not copy objects, they get the reference to the objects.
 | 
				
			||||||
 | 
						assert_ptr(x, ==, vec->data.v_vector3.x, "should reference x"); | 
				
			||||||
 | 
						assert_ptr(y, ==, vec->data.v_vector3.y, "should reference y"); | 
				
			||||||
 | 
						assert_ptr(z, ==, vec->data.v_vector3.z, "should reference z"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assert we have integer values correct
 | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.x->data.v_int, ==, 1, "should have correct x"); | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.y->data.v_int, ==, 2, "should have correct y"); | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.z->data.v_int, ==, 3, "should have correct z"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Free all of our objects.
 | 
				
			||||||
 | 
						boot_free(x); | 
				
			||||||
 | 
						boot_free(y); | 
				
			||||||
 | 
						boot_free(z); | 
				
			||||||
 | 
						boot_free(vec); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					munit_case(SUBMIT, test_vec_same_object, { | 
				
			||||||
 | 
						snek_object_t *i = new_snek_integer(1); | 
				
			||||||
 | 
						snek_object_t *vec = new_snek_vector3(i, i, i); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert_ptr_not_null(vec, "should allocate a new object"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Vectors should not copy objects, they get the reference to the objects.
 | 
				
			||||||
 | 
						assert_ptr(i, ==, vec->data.v_vector3.x, "should reference x"); | 
				
			||||||
 | 
						assert_ptr(i, ==, vec->data.v_vector3.y, "should reference y"); | 
				
			||||||
 | 
						assert_ptr(i, ==, vec->data.v_vector3.z, "should reference z"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assert we have integer values correct
 | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.x->data.v_int, ==, 1, "should have correct x"); | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.y->data.v_int, ==, 1, "should have correct y"); | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.z->data.v_int, ==, 1, "should have correct z"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i->data.v_int = 2; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assert we have integer values correct, after update
 | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.x->data.v_int, ==, 2, "should have correct x"); | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.y->data.v_int, ==, 2, "should have correct y"); | 
				
			||||||
 | 
						assert_int(vec->data.v_vector3.z->data.v_int, ==, 2, "should have correct z"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Free all of our objects.
 | 
				
			||||||
 | 
						boot_free(i); | 
				
			||||||
 | 
						boot_free(vec); | 
				
			||||||
 | 
						assert(boot_all_freed()); | 
				
			||||||
 | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() { | 
				
			||||||
 | 
						MunitTest tests[] = { | 
				
			||||||
 | 
							munit_test("/returns_null", test_returns_null), | 
				
			||||||
 | 
							munit_test("/multiple_objects", test_vec_multiple_objects), | 
				
			||||||
 | 
							munit_test("/same_object", test_vec_same_object), | 
				
			||||||
 | 
							munit_null_test, | 
				
			||||||
 | 
						}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MunitSuite suite = munit_suite("object-vector", tests); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return munit_suite_main(&suite, NULL, 0, NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,61 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 = (snek_object_t *)boot_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; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// don't touch below this line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_integer(int value) { | 
				
			||||||
 | 
						snek_object_t *obj = boot_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 = boot_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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len = strlen(value); | 
				
			||||||
 | 
						char *dst = boot_malloc(len + 1); | 
				
			||||||
 | 
						if (dst == NULL) { | 
				
			||||||
 | 
							boot_free(obj); | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strcpy(dst, value); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj->kind = STRING; | 
				
			||||||
 | 
						obj->data.v_string = dst; | 
				
			||||||
 | 
						return obj; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,31 @@ | 
				
			|||||||
 | 
					typedef struct SnekObject snek_object_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum SnekObjectKind { | 
				
			||||||
 | 
						INTEGER, | 
				
			||||||
 | 
						FLOAT, | 
				
			||||||
 | 
						STRING, | 
				
			||||||
 | 
						VECTOR3, | 
				
			||||||
 | 
					} snek_object_kind_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct SnekVector { | 
				
			||||||
 | 
						snek_object_t *x; | 
				
			||||||
 | 
						snek_object_t *y; | 
				
			||||||
 | 
						snek_object_t *z; | 
				
			||||||
 | 
					} snek_vector_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union SnekObjectData { | 
				
			||||||
 | 
						int v_int; | 
				
			||||||
 | 
						float v_float; | 
				
			||||||
 | 
						char* v_string; | 
				
			||||||
 | 
						snek_vector_t v_vector3; | 
				
			||||||
 | 
					} 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); | 
				
			||||||
@ -0,0 +1,39 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(obj->data.v_array.elements); | 
				
			||||||
 | 
						boot_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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(obj->data.v_array.elements); | 
				
			||||||
 | 
						boot_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,82 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#include "snekobject.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snek_object_t *new_snek_array(size_t size) { | 
				
			||||||
 | 
						snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) return NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snek_object_t **arr = (snek_object_t **)boot_calloc(size, sizeof(snek_object_t *)); | 
				
			||||||
 | 
						if (arr == NULL) { | 
				
			||||||
 | 
							boot_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 = boot_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 = boot_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 = boot_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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len = strlen(value); | 
				
			||||||
 | 
						char *dst = boot_malloc(len + 1); | 
				
			||||||
 | 
						if (dst == NULL) { | 
				
			||||||
 | 
							boot_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,84 @@ | 
				
			|||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(first->data.v_string); | 
				
			||||||
 | 
						boot_free(first); | 
				
			||||||
 | 
						boot_free(second); | 
				
			||||||
 | 
						boot_free(obj->data.v_array.elements); | 
				
			||||||
 | 
						boot_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
 | 
				
			||||||
 | 
						boot_free(outside->data.v_string); | 
				
			||||||
 | 
						boot_free(outside); | 
				
			||||||
 | 
						boot_free(obj->data.v_array.elements); | 
				
			||||||
 | 
						boot_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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(first->data.v_string); | 
				
			||||||
 | 
						boot_free(first); | 
				
			||||||
 | 
						boot_free(obj->data.v_array.elements); | 
				
			||||||
 | 
						boot_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,102 @@ | 
				
			|||||||
 | 
					#include <stdbool.h> | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <string.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bootlib.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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *)); | 
				
			||||||
 | 
						if (elements == NULL) { | 
				
			||||||
 | 
							boot_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 = boot_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 = boot_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 = boot_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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len = strlen(value); | 
				
			||||||
 | 
						char *dst = boot_malloc(len + 1); | 
				
			||||||
 | 
						if (dst == NULL) { | 
				
			||||||
 | 
							boot_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,75 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_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" | 
				
			||||||
 | 
						); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(shorter->data.v_string); | 
				
			||||||
 | 
						boot_free(shorter); | 
				
			||||||
 | 
						boot_free(longer->data.v_string); | 
				
			||||||
 | 
						boot_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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(i); | 
				
			||||||
 | 
						boot_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"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						boot_free(i); | 
				
			||||||
 | 
						boot_free(arr->data.v_array.elements); | 
				
			||||||
 | 
						boot_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,128 @@ | 
				
			|||||||
 | 
					#include "bootlib.h" | 
				
			||||||
 | 
					#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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *)); | 
				
			||||||
 | 
						if (elements == NULL) { | 
				
			||||||
 | 
							boot_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 = boot_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 = boot_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 = boot_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 = boot_malloc(sizeof(snek_object_t)); | 
				
			||||||
 | 
						if (obj == NULL) { | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len = strlen(value); | 
				
			||||||
 | 
						char *dst = boot_malloc(len + 1); | 
				
			||||||
 | 
						if (dst == NULL) { | 
				
			||||||
 | 
							boot_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); | 
				
			||||||
@ -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; | 
				
			||||||
 | 
					} | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
					Loading…
					
					
				
		Reference in new issue