diff --git a/alisp.org b/alisp.org index 6173c07..c8931c8 100644 --- a/alisp.org +++ b/alisp.org @@ -50,7 +50,7 @@ other state do we need to encode? *** TODO Write a parser for lists *** TODO Write a parser for vectors *** TODO Write the general parser -** WIP Unit tests :tests: +** Unit tests :tests: *** TODO Test streams **** DONE Test file init [[file:test/test_stream.c::void stream_test_file(void)]] @@ -100,8 +100,17 @@ Also ensure stream_eoc is false. *** DONE Test system registration of allocated units In particular, does clean up work as we expect? Do we have situations where we may double free or not clean up something we should've? +** String views :sv_t: +[[file:include/alisp/sv.h::/// String Views]] +*** DONE sv_substr +Takes an index and a size, returns a string view to that substring. +*** DONE sv_chop_left and sv_chop_right +Super obvious. +*** TODO Design Strings for the Lisp :api: +We have ~sv_t~ so our basic C API is done. We just need pluggable +functions to construct and deconstruct strings as lisps. ** Backlog -*** TODO Design Big Integers +*** TODO Design Big Integers :api: We currently have 62 bit integers implemented via immediate values embedded in a pointer. We need to be able to support even _bigger_ integers. How do we do this? @@ -189,19 +198,10 @@ Latter approach time complexity: Former approach is better time complexity wise, but latter is way better in terms of simplicity of code. Must deliberate. -*** TODO Design Strings -We have ~sv_t~ so our basic C API is done. We just need pluggable -functions to construct and deconstruct strings as lisps. *** TODO Capitalise symbols (TBD) :optimisation:design: Should we capitalise symbols? This way, we limit the symbol table's possible options a bit (potentially we could design a better hashing algorithm?) and it would be kinda like an actual Lisp. -*** TODO sv_t -[[file:include/alisp/sv.h::/// String Views]] -**** TODO sv_substr -Takes an index and a size, returns a string view to that substring. -**** TODO sv_chop_left and sv_chop_right -Super obvious. ** Completed *** DONE Test value constructors and destructors :test: Test if ~make_int~ works with ~as_int,~ ~intern~ with ~as_sym~. diff --git a/include/alisp/sv.h b/include/alisp/sv.h index 1f414b7..d5291f2 100644 --- a/include/alisp/sv.h +++ b/include/alisp/sv.h @@ -26,6 +26,13 @@ typedef struct // String view functions sv_t sv_copy(sv_t); +sv_t sv_chop_left(sv_t, u64 size); +sv_t sv_chop_right(sv_t, u64 size); +sv_t sv_substr(sv_t, u64 position, u64 size); +sv_t sv_truncate(sv_t, u64 newsize); + +sv_t sv_till(sv_t, const char *reject); +sv_t sv_while(sv_t, const char *accept); #endif diff --git a/src/sv.c b/src/sv.c index 1fb8521..d765651 100644 --- a/src/sv.c +++ b/src/sv.c @@ -22,6 +22,62 @@ sv_t sv_copy(sv_t old) return SV(newstr, old.size); } +sv_t sv_chop_left(sv_t sv, u64 size) +{ + if (sv.size <= size) + return SV(NULL, 0); + return SV(sv.data + size, sv.size - size); +} + +sv_t sv_chop_right(sv_t sv, u64 size) +{ + if (sv.size <= size) + return SV(NULL, 0); + return SV(sv.data, sv.size - size); +} + +sv_t sv_substr(sv_t sv, u64 position, u64 size) +{ + return sv_chop_right(sv_chop_left(sv, position), size); +} + +sv_t sv_truncate(sv_t sv, u64 newsize) +{ + if (newsize >= sv.size) + return sv; + return SV(sv.data, newsize); +} + +sv_t sv_till(sv_t sv, const char *reject) +{ + if (sv.size == 0 || !sv.data) + return SV(NULL, 0); + + u64 offset; + for (offset = 0; offset < sv.size && strchr(reject, sv.data[offset]) == NULL; + ++offset) + continue; + + if (offset == sv.size) + return sv; + return sv_chop_right(sv, sv.size - offset); +} + +sv_t sv_while(sv_t sv, const char *accept) +{ + if (sv.size == 0 || !sv.data) + return SV(NULL, 0); + + u64 offset; + for (offset = 0; offset < sv.size && strchr(accept, sv.data[offset]) != NULL; + ++offset) + continue; + + if (offset == sv.size) + return sv; + return sv_chop_right(sv, sv.size - offset); +} + /* Copyright (C) 2025, 2026 Aryadev Chavali * This program is distributed in the hope that it will be useful, but WITHOUT