Make nicer primitive functions for car/cdr

If it isn't a CONS, we return NIL instead of failing.  This way, we
can use it in our general iteration functions.  Eventually the actual
runtime would use this as well.  The macros are mostly for internal
use to do assignment etc.
This commit is contained in:
2025-08-21 14:54:57 +01:00
parent 742f19886c
commit 0f68afd9a0
3 changed files with 24 additions and 4 deletions

View File

@@ -126,6 +126,9 @@ vec_t *as_vec(lisp_t *);
#define CAR(L) (as_cons(L)->car) #define CAR(L) (as_cons(L)->car)
#define CDR(L) (as_cons(L)->cdr) #define CDR(L) (as_cons(L)->cdr)
lisp_t *car(lisp_t *);
lisp_t *cdr(lisp_t *);
/// Pointer tagging scheme for lisps /// Pointer tagging scheme for lisps
typedef enum Tag typedef enum Tag

View File

@@ -46,3 +46,19 @@ lisp_t *intern(sys_t *sys, sv_t sv)
char *str = sym_table_find(&sys->symtable, sv); char *str = sym_table_find(&sys->symtable, sv);
return tag_sym(str); return tag_sym(str);
} }
lisp_t *car(lisp_t *lsp)
{
if (!IS_TAG(lsp, CONS))
return NIL;
else
return CAR(lsp);
}
lisp_t *cdr(lisp_t *lsp)
{
if (!IS_TAG(lsp, CONS))
return NIL;
else
return CDR(lsp);
}

9
sys.c
View File

@@ -43,12 +43,13 @@ void sys_cleanup(sys_t *sys)
return; return;
// Iterate through each element of memory // Iterate through each element of memory
for (lisp_t *cell = sys->memory, *next = CDR(cell); cell; for (lisp_t *cell = sys->memory, *next = cdr(cell); cell;
cell = next, next = CDR(cell)) cell = next, next = cdr(next))
{ {
// Only reason allocated exists is because we had to allocate memory on the // Only reason allocated exists is because we had to allocate memory on the
// heap for it. It's therefore // heap for it. It's therefore enough to deal with only the allocated
lisp_t *allocated = CAR(cell); // types.
lisp_t *allocated = car(cell);
switch (get_tag(allocated)) switch (get_tag(allocated))
{ {
case TAG_CONS: case TAG_CONS: