alisp.org: rework TODOs, setup one for allocators.

This commit is contained in:
2026-02-12 23:03:05 +00:00
parent 042cc48e8c
commit 79f53c7916

169
alisp.org
View File

@@ -4,6 +4,15 @@
#+filetags: :alisp: #+filetags: :alisp:
* Tasks * Tasks
** String views :strings:
[[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.
** Reader system :reader: ** Reader system :reader:
We need to design a reader system. The big idea: given a "stream" of We need to design a reader system. The big idea: given a "stream" of
data, we can break out expressions from it. An expression could be data, we can break out expressions from it. An expression could be
@@ -52,85 +61,50 @@ other state do we need to encode?
*** TODO Write a parser for strings *** TODO Write a parser for strings
Requires [[*Design Strings for the Lisp]] to be complete first. Requires [[*Design Strings for the Lisp]] to be complete first.
*** TODO Write the general parser *** TODO Write the general parser
** Unit tests :tests:
*** TODO Test streams :streams:
**** DONE Test file init
[[file:test/test_stream.c::void stream_test_file(void)]]
***** DONE Test successful init from real files
Ensure stream_size is 0 i.e. we don't read anything on creation.
Also ensure stream_eoc is false.
***** DONE Test failed init from fake files
**** DONE Test peeking and next
[[file:test/test_stream.c::void stream_test_peek_next(void)]]
- Peeking with bad streams ('\0' return)
- Peeking with good streams (no effect on position)
- Next with bad streams ('\0' return, no effect on position)
- Next with good streams (effects position)
- Peeking after next (should just work)
**** DONE Test seeking
[[file:test/test_stream.c::void stream_test_seek(void)]]
- Seeking forward/backward on a bad stream (should stop at 0)
- Seeking forward/backward too far (should clamp)
- Seeking forward/backward zero sum via relative index (stream_seek)
**** DONE Test substring
[[file:test/test_stream.c::void stream_test_substr(void)]]
- Substr on bad stream (NULL sv)
- Substr on bad position/size (NULL sv)
- Substr relative/absolute (good SV)
**** TODO Test till
[[file:test/test_stream.c::void stream_test_till(void)]]
- till on a bad stream (NULL SV)
- till on an ended stream (NULL SV)
- till on a stream with no items in search string (eoc)
- till on a stream with all items in search string (no effect)
- till on a stream with prefix being all search string (no effect)
- till on a stream with suffix being all search string (stops at
suffix)
**** TODO Test while
[[file:test/test_stream.c::void stream_test_while(void)]]
- while on a bad stream (NULL SV)
- while on an ended stream (NULL SV)
- while on a stream with no items in search string (no effect)
- while on a stream with all items in search string (eoc)
- while on a stream with prefix being all search string (effect)
- while on a stream with suffix being all search string (no effect)
**** TODO Test line_col
[[file:test/test_stream.c::void stream_test_line_col(void)]]
- line_col on bad stream (no effect on args)
- line_col on eoc stream (should go right to the end)
- line_col on random points in a stream
*** TODO Test reader :reader:
*** 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 :strings:
[[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.
** Design :design: ** Design :design:
*** TODO Design Big Integers :api: *** TODO Design Big Integers :api:
We currently have 62 bit integers implemented via immediate values We currently have 62 bit integers implemented via immediate values
embedded in a pointer. We need to be able to support even _bigger_ embedded in a pointer. We need to be able to support even _bigger_
integers. How do we do this? integers. How do we do this?
*** TODO Design garbage collection scheme :gc: *** TODO Capitalise symbols (TBD) :optimisation:
Really, regardless of what I do, we need to have some kind of garbage Should we capitalise symbols? This way, we limit the symbol table's
collection header on whatever managed objects we allocate. possible options a bit (potentially we could design a better hashing
algorithm?) and it would be kinda like an actual Lisp.
*** TODO Consider reader macros :reader:
Common Lisp has so-called "reader macros" which allows users to write
Lisp code that affects further Lisp code reading. It's quite
powerful.
Firstly, the distinction between managed and unmanaged objects: Scheme doesn't have it. Should we implement this?
** Allocator :allocator:
*** Some definitions
- Managed objects are allocations that are generated as part of - Managed objects are allocations that are generated as part of
evaluating user code i.e. strings, vectors, conses that are all made evaluating user code i.e. strings, vectors, conses that are all made
as part of evaluating code. as part of evaluating code.
- Unmanaged objects are allocations we do as part of the runtime. - Unmanaged objects are allocations we do as part of the runtime.
These are things that we expect to have near infinite lifetimes These are things that we expect to have near infinite lifetimes
(such as the symbol table, vector of allocated objects, etc). (such as the symbol table, vector of allocated objects, etc).
*** TODO Design an allocator
We need to perform garbage collection against the managed objects, and We'll need an allocator for all our managed objects. Requirements:
leave the unmanaged objects to the runtime. - Stable pointers (memory that has already been allocated should be
free to utilise via the same pointer for the lifetime of the
allocator)
- Able to tag allocations as unused (i.e. "free") and able to reuse
these allocations
- This will link into the garbage collector, which should yield a
sequence of objects that should be "freed".
- Able to allocate all the managed types we have
**** TODO Design allocation data structures
**** TODO Design allocation methods for different lisp types
- Conses
- Vectors
- Strings (when implemented)
**** TODO Design allocation freeing methods
*** TODO Design garbage collection scheme :gc:
Really, regardless of what I do, we need to have some kind of garbage
collection header on whatever managed objects we allocate. We need to
perform garbage collection against the managed objects, and leave the
unmanaged objects to the runtime.
**** TODO Mark stage **** TODO Mark stage
We need to mark all objects that are currently accessible from the We need to mark all objects that are currently accessible from the
environment. This means we need to have a root environment which we environment. This means we need to have a root environment which we
@@ -201,16 +175,57 @@ Latter approach time complexity:
Former approach is better time complexity wise, but latter is way Former approach is better time complexity wise, but latter is way
better in terms of simplicity of code. Must deliberate. better in terms of simplicity of code. Must deliberate.
*** TODO Capitalise symbols (TBD) :optimisation: ** Unit tests :tests:
Should we capitalise symbols? This way, we limit the symbol table's *** TODO Test streams :streams:
possible options a bit (potentially we could design a better hashing **** DONE Test file init
algorithm?) and it would be kinda like an actual Lisp. [[file:test/test_stream.c::void stream_test_file(void)]]
*** TODO Consider reader macros :reader: ***** DONE Test successful init from real files
Common Lisp has so-called "reader macros" which allows users to write Ensure stream_size is 0 i.e. we don't read anything on creation.
Lisp code that affects further Lisp code reading. It's quite Also ensure stream_eoc is false.
powerful. ***** DONE Test failed init from fake files
**** DONE Test peeking and next
Scheme doesn't have it. Should we implement this? [[file:test/test_stream.c::void stream_test_peek_next(void)]]
- Peeking with bad streams ('\0' return)
- Peeking with good streams (no effect on position)
- Next with bad streams ('\0' return, no effect on position)
- Next with good streams (effects position)
- Peeking after next (should just work)
**** DONE Test seeking
[[file:test/test_stream.c::void stream_test_seek(void)]]
- Seeking forward/backward on a bad stream (should stop at 0)
- Seeking forward/backward too far (should clamp)
- Seeking forward/backward zero sum via relative index (stream_seek)
**** DONE Test substring
[[file:test/test_stream.c::void stream_test_substr(void)]]
- Substr on bad stream (NULL sv)
- Substr on bad position/size (NULL sv)
- Substr relative/absolute (good SV)
**** TODO Test till
[[file:test/test_stream.c::void stream_test_till(void)]]
- till on a bad stream (NULL SV)
- till on an ended stream (NULL SV)
- till on a stream with no items in search string (eoc)
- till on a stream with all items in search string (no effect)
- till on a stream with prefix being all search string (no effect)
- till on a stream with suffix being all search string (stops at
suffix)
**** TODO Test while
[[file:test/test_stream.c::void stream_test_while(void)]]
- while on a bad stream (NULL SV)
- while on an ended stream (NULL SV)
- while on a stream with no items in search string (no effect)
- while on a stream with all items in search string (eoc)
- while on a stream with prefix being all search string (effect)
- while on a stream with suffix being all search string (no effect)
**** TODO Test line_col
[[file:test/test_stream.c::void stream_test_line_col(void)]]
- line_col on bad stream (no effect on args)
- line_col on eoc stream (should go right to the end)
- line_col on random points in a stream
*** TODO Test reader :reader:
*** 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?
** Completed ** Completed
*** DONE Test value constructors and destructors :test: *** DONE Test value constructors and destructors :test:
Test if ~make_int~ works with ~as_int,~ ~intern~ with ~as_sym~. Test if ~make_int~ works with ~as_int,~ ~intern~ with ~as_sym~.