Browse Source

Add more exercises

master
Riyyi 1 week ago
parent
commit
ec77cf9a1d
  1. 7
      README.org
  2. 30
      src/9-1-snek-objects/main.c
  3. 13
      src/9-1-snek-objects/snekobject.h
  4. 40
      src/9-2-integer/main.c
  5. 11
      src/9-2-integer/snekobject.c
  6. 14
      src/9-2-integer/snekobject.h
  7. 45
      src/9-3-float/main.c
  8. 24
      src/9-3-float/snekobject.c
  9. 17
      src/9-3-float/snekobject.h
  10. 41
      src/9-4-string/main.c
  11. 46
      src/9-4-string/snekobject.c
  12. 20
      src/9-4-string/snekobject.h
  13. 81
      src/9-5-vector3/main.c
  14. 69
      src/9-5-vector3/snekobject.c
  15. 31
      src/9-5-vector3/snekobject.h
  16. 6
      src/munit.h

7
README.org

@ -8,6 +8,9 @@ Completed course from
The exercises from the course have been worked out in this repo. The exercises from the course have been worked out in this repo.
This is my way of having the "certificate" for free. This is my way of having 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, If you're reading this with the intention of completing the exercises yourself,
just remove the directories from the =src= directory and recreate the directory just remove the directories from the =src= directory and recreate the directory
@ -21,10 +24,6 @@ Note:
- In chapter 8, I renamed ~stack_t~ to ~my_stack_t~ due to a =std= naming - In chapter 8, I renamed ~stack_t~ to ~my_stack_t~ due to a =std= naming
conflict on macOS conflict on macOS
The first the 3 chapters of the course can be done interactively on the website.
[[./bootdev-c.png]]
** Build instructions ** Build instructions
Compiling and running all the tests can be done with the following commands: Compiling and running all the tests can be done with the following commands:

30
src/9-1-snek-objects/main.c

@ -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);
}

13
src/9-1-snek-objects/snekobject.h

@ -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;

40
src/9-2-integer/main.c

@ -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);
}

11
src/9-2-integer/snekobject.c

@ -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;
}

14
src/9-2-integer/snekobject.h

@ -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);

45
src/9-3-float/main.c

@ -0,0 +1,45 @@
#include <stdlib.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");
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");
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");
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);
}

24
src/9-3-float/snekobject.c

@ -0,0 +1,24 @@
#include <stdlib.h>
#include "snekobject.h"
snek_object_t *new_snek_float(float value) {
snek_object_t *obj = (snek_object_t *)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 = malloc(sizeof(snek_object_t));
if (obj == NULL) {
return NULL;
}
obj->kind = INTEGER;
obj->data.v_int = value;
return obj;
}

17
src/9-3-float/snekobject.h

@ -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);

41
src/9-4-string/main.c

@ -0,0 +1,41 @@
#include <stdlib.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.
// assert_int_equal(boot_alloc_size(), 22, "Must allocate memory for string");
// Free the string, and then free the object.
free(obj->data.v_string);
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);
}

46
src/9-4-string/snekobject.c

@ -0,0 +1,46 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "snekobject.h"
snek_object_t *new_snek_string(char *value) {
snek_object_t *obj = malloc(sizeof(snek_object_t));
if (obj == NULL) return NULL;
size_t size = strlen(value);
char *str = (char *)malloc(sizeof(char) * size + 1);
if (str == NULL) {
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 = malloc(sizeof(snek_object_t));
if (obj == NULL) {
return NULL;
}
obj->kind = INTEGER;
obj->data.v_int = value;
return obj;
}
snek_object_t *new_snek_float(float value) {
snek_object_t *obj = malloc(sizeof(snek_object_t));
if (obj == NULL) {
return NULL;
}
obj->kind = FLOAT;
obj->data.v_float = value;
return obj;
}

20
src/9-4-string/snekobject.h

@ -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);

81
src/9-5-vector3/main.c

@ -0,0 +1,81 @@
#include <stdlib.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.
free(x);
free(y);
free(z);
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.
free(i);
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);
}

69
src/9-5-vector3/snekobject.c

@ -0,0 +1,69 @@
#include <stdlib.h>
#include <string.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 *)malloc(sizeof(snek_object_t));
if (obj == NULL) return NULL;
snek_vector_t *vec = (snek_vector_t *)malloc(sizeof(snek_vector_t));
if (vec == NULL) {
free(obj);
return NULL;
}
vec->x = x;
vec->y = y;
vec->z = z;
obj->kind = VECTOR3;
obj->data.v_vector3 = *vec;
return obj;
}
// don't touch below this line
snek_object_t *new_snek_integer(int value) {
snek_object_t *obj = malloc(sizeof(snek_object_t));
if (obj == NULL) {
return NULL;
}
obj->kind = INTEGER;
obj->data.v_int = value;
return obj;
}
snek_object_t *new_snek_float(float value) {
snek_object_t *obj = malloc(sizeof(snek_object_t));
if (obj == NULL) {
return NULL;
}
obj->kind = FLOAT;
obj->data.v_float = value;
return obj;
}
snek_object_t *new_snek_string(char *value) {
snek_object_t *obj = malloc(sizeof(snek_object_t));
if (obj == NULL) {
return NULL;
}
int len = strlen(value);
char *dst = malloc(len + 1);
if (dst == NULL) {
free(obj);
return NULL;
}
strcpy(dst, value);
obj->kind = STRING;
obj->data.v_string = dst;
return obj;
}

31
src/9-5-vector3/snekobject.h

@ -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);

6
src/munit.h

@ -105,8 +105,14 @@
#define munit_assert_ptr_not_equal(A, B, MSG) \ #define munit_assert_ptr_not_equal(A, B, MSG) \
munit_assert_ptr(A, !=, B) munit_assert_ptr(A, !=, B)
#undef assert_ptr
#define assert_ptr(A, OP, B, MSG) munit_assert_ptr(A, OP, B)
#undef assert_ptr_not_null #undef assert_ptr_not_null
#define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG) #define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG)
#undef assert_ptr_equal #undef assert_ptr_equal
#define assert_ptr_equal(A, B, MSG) munit_assert_ptr_equal(A, B) #define assert_ptr_equal(A, B, MSG) munit_assert_ptr_equal(A, B)
#undef assert_ptr_not_equal
#define assert_ptr_not_equal(A, B, MSG) munit_assert_ptr_not_equal(A, B, MSG)

Loading…
Cancel
Save