diff options
-rw-r--r-- | build.sh | 4 | ||||
-rw-r--r-- | impl/constructor.c (renamed from constructor.c) | 2 | ||||
-rw-r--r-- | impl/stream.c (renamed from stream.c) | 2 | ||||
-rw-r--r-- | impl/sv.c (renamed from sv.c) | 2 | ||||
-rw-r--r-- | impl/symtable.c (renamed from symtable.c) | 2 | ||||
-rw-r--r-- | impl/sys.c (renamed from sys.c) | 2 | ||||
-rw-r--r-- | impl/tag.c (renamed from tag.c) | 2 | ||||
-rw-r--r-- | impl/test.c | 238 | ||||
-rw-r--r-- | impl/vec.c (renamed from vec.c) | 2 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | test.c | 2 |
11 files changed, 249 insertions, 11 deletions
@@ -3,8 +3,8 @@ set -xe CFLAGS="-Wall -Wextra -std=c11 -ggdb -fsanitize=address -fsanitize=undefined" -LINK="" -LIB="sv.c vec.c symtable.c tag.c constructor.c stream.c sys.c" +LINK="-I." +LIB="impl/sv.c impl/vec.c impl/symtable.c impl/tag.c impl/constructor.c impl/stream.c impl/sys.c" OUT="alisp.out" build() { diff --git a/constructor.c b/impl/constructor.c index e0fab52..4c8efa4 100644 --- a/constructor.c +++ b/impl/constructor.c @@ -14,7 +14,7 @@ #include <malloc.h> -#include "./alisp.h" +#include <alisp.h> lisp_t *make_int(i64 i) { @@ -14,7 +14,7 @@ #include <string.h> -#include "./alisp.h" +#include <alisp.h> stream_err_t stream_init_string(stream_t *stream, char *name, sv_t contents) { @@ -16,7 +16,7 @@ #include <malloc.h> #include <string.h> -#include "./alisp.h" +#include <alisp.h> sv_t sv_copy(sv_t old) { diff --git a/symtable.c b/impl/symtable.c index 39139eb..abef727 100644 --- a/symtable.c +++ b/impl/symtable.c @@ -12,7 +12,7 @@ * Description: Symbol Table implementation */ -#include "./alisp.h" +#include <alisp.h> #include <malloc.h> #include <string.h> @@ -12,7 +12,7 @@ * Description: System management */ -#include "./alisp.h" +#include <alisp.h> #include <assert.h> #include <malloc.h> @@ -15,7 +15,7 @@ #include <assert.h> #include <stdlib.h> -#include "./alisp.h" +#include <alisp.h> lisp_t *tag_int(i64 i) { diff --git a/impl/test.c b/impl/test.c new file mode 100644 index 0000000..e517286 --- /dev/null +++ b/impl/test.c @@ -0,0 +1,238 @@ +/* Copyright (C) 2025 Aryadev Chavali + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Unlicense + * for details. + + * You may distribute and modify this code under the terms of the + * Unlicense, which you should have received a copy of along with this + * program. If not, please go to <https://unlicense.org/>. + + * Created: 2025-08-21 + * Description: Tests + */ + +#include <stdio.h> +#include <string.h> + +#include <alisp.h> + +#define TEST_PASSED() printf("[%s]: Pass\n", __func__) +#define TEST(NAME, COND) \ + do \ + { \ + if (!(COND)) \ + { \ + printf("[%s]: `%s` failed!\n", __func__, (NAME)); \ + assert(0); \ + } \ + } while (0) + +// Sample data +const char *unique_words[] = { + "bibendum", "etiam", "gravida", "dui", "cursus", + "purus", "diam", "phasellus", "nam", "fermentum", + "leo", "enim", "ac", "semper", "non", + "mauris", "proin", "tellus", "vivamus", "lobortis", + "lacus", "neque", "in", "nullam", "felis", + "orci", "pede", "tempus", "nec", "at", + "tortor", "massa", "sed", "magna", "eget", + "tempor", "velit", "imperdiet", "praesent", "volutpat", + "tristique", "id", "commodo", "aliquet", "quis", + "pellentesque", "eleifend", "porta", "nunc", "euismod", + "aliquam", "a", "erat", "dignissim", "ut", + "vitae", "vel", "donec", +}; + +char *words[] = { + "aliquam", "erat", "volutpat", "nunc", "eleifend", + "leo", "vitae", "magna", "in", "id", + "erat", "non", "orci", "commodo", "lobortis", + "proin", "neque", "massa", "cursus", "ut", + "gravida", "ut", "lobortis", "eget", "lacus", + "sed", "diam", "praesent", "fermentum", "tempor", + "tellus", "nullam", "tempus", "mauris", "ac", + "felis", "vel", "velit", "tristique", "imperdiet", + "donec", "at", "pede", "etiam", "vel", + "neque", "nec", "dui", "dignissim", "bibendum", + "vivamus", "id", "enim", "phasellus", "neque", + "orci", "porta", "a", "aliquet", "quis", + "semper", "a", "massa", "phasellus", "purus", + "pellentesque", "tristique", "imperdiet", "tortor", "nam", + "euismod", "tellus", "id", "erat", +}; + +char words_text[] = + "aliquam erat volutpat nunc eleifend leo vitae magna in id erat non orci " + "commodo lobortis proin neque massa cursus ut gravida ut lobortis eget " + "lacus sed diam praesent fermentum tempor tellus nullam tempus mauris ac " + "felis vel velit tristique imperdiet donec at pede etiam vel neque nec dui " + "dignissim bibendum vivamus id enim phasellus neque orci porta a aliquet " + "quis semper a massa phasellus purus pellentesque tristique imperdiet " + "tortor nam euismod tellus id erat"; + +char text[] = + "Pellentesque dapibus suscipit ligula. Donec posuere augue in quam. " + "Etiam vel tortor sodales tellus ultricies commodo. Suspendisse potenti. " + "Aenean in sem ac leo mollis blandit. Donec neque quam, dignissim in, " + "mollis nec, sagittis eu, wisi. Phasellus lacus. Etiam laoreet quam sed " + "arcu. Phasellus at dui in ligula mollis ultricies. Integer placerat " + "tristique nisl. Praesent augue. Fusce commodo. Vestibulum convallis, " + "lorem a tempus semper, dui dui euismod elit, vitae placerat urna tortor " + "vitae lacus. Nullam libero mauris, consequat quis, varius et, dictum id, " + "arcu. Mauris mollis tincidunt felis. Aliquam feugiat tellus ut neque. " + "Nulla facilisis, risus a rhoncus fermentum, tellus tellus lacinia purus, " + "et dictum nunc justo sit amet elit."; + +void symtable_test(void) +{ + sym_table_t table = {0}; + sym_table_init(&table); + for (u64 i = 0; i < ARRSIZE(words); ++i) + sym_table_find(&table, SV(words[i], strlen(words[i]))); + + TEST("|table|=|set(words)|", table.count == ARRSIZE(unique_words)); + TEST("|table| < |words|", table.count < ARRSIZE(words)); + + TEST_PASSED(); + + sym_table_cleanup(&table); +} + +void int_test(void) +{ + i64 ints[] = { + 1, -1, (1 << 10) - 1, (-1) * ((1 << 10) - 1), INT_MIN, INT_MAX, + }; + + for (u64 i = 0; i < ARRSIZE(ints); ++i) + { + i64 in = ints[i]; + lisp_t *lisp = make_int(in); + i64 out = as_int(lisp); + + TEST("in == out", in == out); + } + + TEST_PASSED(); +} + +void sym_test(void) +{ + sys_t system = {0}; + sys_init(&system); + for (u64 i = 0; i < ARRSIZE(words); ++i) + { + char *in = words[i]; + lisp_t *lisp = intern(&system, SV(in, strlen(in))); + char *out = as_sym(lisp); + TEST("unique pointers when interning a symbol", in != out); + TEST("same size", strlen(in) == strlen(out)); + TEST("same string", strncmp(in, out, strlen(in)) == 0); + } + TEST_PASSED(); + sys_cleanup(&system); +} + +void vec_test1(void) +{ + sys_t system = {0}; + sys_init(&system); + + // Generating a vector word by word + lisp_t *lvec = make_vec(&system, 0); + for (u64 i = 0; i < ARRSIZE(words); ++i) + { + char *word = words[i]; + vec_append(as_vec(lvec), word, strlen(word)); + if (i != ARRSIZE(words) - 1) + vec_append(as_vec(lvec), " ", 1); + } + vec_append(as_vec(lvec), "\0", 1); + + vec_t *vec = as_vec(lvec); + + TEST("same size vector", vec->size == ARRSIZE(words_text)); + TEST("same as actually concatenated string", + strncmp(vec_data(vec), words_text, vec->size) == 0); + + TEST_PASSED(); + sys_cleanup(&system); +} + +void vec_test2(void) +{ + sys_t system = {0}; + sys_init(&system); + // Generating substrings + struct Test + { + u64 start, size; + } tests[] = { + {0, 16}, + {0, 32}, + {32, 64}, + {0, ARRSIZE(text)}, + }; + + for (u64 i = 0; i < ARRSIZE(tests); ++i) + { + struct Test test = tests[i]; + const sv_t substr = SV(text + test.start, test.size); + const u64 size = test.size / 2; + + lisp_t *lvec = make_vec(&system, size); + vec_append(as_vec(lvec), text + test.start, test.size); + TEST("Vector grew", as_vec(lvec)->size > size); + TEST("Vector's substring is equivalent to the actual substring", + strncmp(vec_data(as_vec(lvec)), substr.data, substr.size) == 0); + } + + printf("[vec_test2]: Pass\n"); + sys_cleanup(&system); +} + +void cons_test(void) +{ + sys_t system = {0}; + sys_init(&system); + + // Let's make a list of words using `cons` + lisp_t *lisp = NIL; + for (u64 i = 0; i < ARRSIZE(words); ++i) + { + char *word = words[i]; + lisp_t *lword = intern(&system, SV(word, strlen(word))); + lisp = cons(&system, lword, lisp); + } + + // Make sure we've essentially reversed the `words` array + u64 i = ARRSIZE(words); + for (lisp_t *iter = lisp; iter; iter = cdr(iter)) + { + lisp_t *item = car(iter); + TEST("we've reversed the array", + strncmp(words[i - 1], as_sym(item), strlen(words[i - 1])) == 0); + i -= 1; + } + + TEST_PASSED(); + + sys_cleanup(&system); +} + +typedef void (*test_fn)(void); + +const test_fn TESTS[] = { + int_test, sym_test, vec_test1, vec_test2, cons_test, +}; + +int main(void) +{ + for (u64 i = 0; i < ARRSIZE(TESTS); ++i) + { + TESTS[i](); + } + return 0; +} @@ -16,7 +16,7 @@ #include <malloc.h> #include <string.h> -#include "./alisp.h" +#include <alisp.h> void vec_init(vec_t *vec, u64 size) { @@ -16,7 +16,7 @@ #include <stdio.h> #include <string.h> -#include "./alisp.h" +#include <alisp.h> int main(void) { @@ -16,7 +16,7 @@ #include <stdio.h> #include <string.h> -#include "./alisp.h" +#include <alisp.h> #define TEST_PASSED() printf("[%s]: Pass\n", __func__) #define TEST(NAME, COND) \ |