Compare commits
2 commits
6fa8c4a110
...
86512ca252
Author | SHA1 | Date | |
---|---|---|---|
86512ca252 | |||
0c8b8b251d |
4 changed files with 93 additions and 1 deletions
19
README.md
Normal file
19
README.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Clox
|
||||||
|
|
||||||
|
This is my implmementation of the `clox` programming language, as seen from [Crafting Interpreters]. It makes use of the
|
||||||
|
[meson] build system. For convenience, there's also a `Makefile` included to simplify the (already pretty simple) meson commands.
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test
|
||||||
|
```
|
||||||
|
|
||||||
|
[Crafting Interpreters]: https://craftinginterpreters.com/
|
||||||
|
[meson]: https://mesonbuild.com/
|
|
@ -6,6 +6,7 @@ struct dll_node {
|
||||||
|
|
||||||
typedef struct dll_node dll_node;
|
typedef struct dll_node dll_node;
|
||||||
|
|
||||||
|
// TODO: I probably don't need a separate "list" type
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct dll_node *head;
|
struct dll_node *head;
|
||||||
} dll_list;
|
} dll_list;
|
||||||
|
@ -33,7 +34,17 @@ void dll_list_append(dll_list *list, dll_node *node) {
|
||||||
dll_list_insert(list, node, -1);
|
dll_list_insert(list, node, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find and delete operations on list
|
/**
|
||||||
|
* Searches the given list for a node with a given value
|
||||||
|
* @returns a pointer to the node with the value or NULL if no nodes match the value
|
||||||
|
*/
|
||||||
|
dll_node *dll_list_find(dll_list *list, char *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first node with the matching value in the given list
|
||||||
|
* @returns a pointer to the node with the value or NULL if no nodes match the value
|
||||||
|
*/
|
||||||
|
dll_node *dll_list_delete(dll_list *list, char *value);
|
||||||
|
|
||||||
dll_node *dll_node_new(char *value);
|
dll_node *dll_node_new(char *value);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,39 @@ void dll_list_insert(dll_list *list, dll_node *node, int index) {
|
||||||
current_node->next = node;
|
current_node->next = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dll_node *dll_list_find(dll_list *list, char *value) {
|
||||||
|
if (list == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dll_node *current_node = list->head;
|
||||||
|
while (current_node != NULL) {
|
||||||
|
if (strcmp(current_node->value, value) == 0) {
|
||||||
|
return current_node;
|
||||||
|
}
|
||||||
|
current_node = current_node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dll_node *dll_list_delete(dll_list *list, char *value) {
|
||||||
|
dll_node *target_node = dll_list_find(list, value);
|
||||||
|
if (target_node == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_node->previous != NULL) {
|
||||||
|
target_node->previous->next = target_node->next;
|
||||||
|
} else {
|
||||||
|
list->head = target_node->next;
|
||||||
|
}
|
||||||
|
if (target_node->next != NULL) {
|
||||||
|
target_node->next->previous = target_node->previous;
|
||||||
|
}
|
||||||
|
return target_node;
|
||||||
|
}
|
||||||
|
|
||||||
dll_node *dll_node_new(char *value) {
|
dll_node *dll_node_new(char *value) {
|
||||||
dll_node *node = malloc(sizeof(dll_node));
|
dll_node *node = malloc(sizeof(dll_node));
|
||||||
node->previous = NULL;
|
node->previous = NULL;
|
||||||
|
|
29
test/dll.c
29
test/dll.c
|
@ -8,6 +8,17 @@ dll_list *list = NULL;
|
||||||
dll_node *head = NULL;
|
dll_node *head = NULL;
|
||||||
char *list_string = NULL;
|
char *list_string = NULL;
|
||||||
|
|
||||||
|
#define ASSERT_PTR_EQ(expected, actual) \
|
||||||
|
{ \
|
||||||
|
if (expected != actual) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"pointers don't match. expected: \"%p\", actual: \"%p\"\n", \
|
||||||
|
(void*)expected, (void*)actual); \
|
||||||
|
cleanup(); \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define ASSERT_STR_EQ(expected, actual) \
|
#define ASSERT_STR_EQ(expected, actual) \
|
||||||
{ \
|
{ \
|
||||||
if (strcmp(expected, actual) != 0) { \
|
if (strcmp(expected, actual) != 0) { \
|
||||||
|
@ -71,6 +82,7 @@ int main(int argc, char **argv) {
|
||||||
dll_list_append(list, head);
|
dll_list_append(list, head);
|
||||||
head = NULL;
|
head = NULL;
|
||||||
// TODO: Extract test utilities to shared file
|
// TODO: Extract test utilities to shared file
|
||||||
|
// TODO: Maybe break these out into separate files?
|
||||||
list_string = list_to_string(list);
|
list_string = list_to_string(list);
|
||||||
ASSERT_STR_EQ("0", list_string);
|
ASSERT_STR_EQ("0", list_string);
|
||||||
|
|
||||||
|
@ -88,6 +100,23 @@ int main(int argc, char **argv) {
|
||||||
list_string = list_to_string(list);
|
list_string = list_to_string(list);
|
||||||
ASSERT_STR_EQ("0, 1, 2", list_string);
|
ASSERT_STR_EQ("0, 1, 2", list_string);
|
||||||
|
|
||||||
|
ASSERT_PTR_EQ(second, dll_list_find(list, "1"));
|
||||||
|
|
||||||
|
ASSERT_PTR_EQ(third, dll_list_delete(list, "2"));
|
||||||
|
dll_node_free(third);
|
||||||
|
|
||||||
|
free(list_string);
|
||||||
|
list_string = list_to_string(list);
|
||||||
|
ASSERT_STR_EQ("0, 1", list_string);
|
||||||
|
|
||||||
|
head = list->head;
|
||||||
|
ASSERT_PTR_EQ(head, dll_list_delete(list, "0"));
|
||||||
|
dll_node_free(head);
|
||||||
|
|
||||||
|
free(list_string);
|
||||||
|
list_string = list_to_string(list);
|
||||||
|
ASSERT_STR_EQ("1", list_string);
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue