This commit is contained in:
2026-01-16 03:20:38 -08:00
parent e0d8693840
commit 94d5749d31
19 changed files with 1358 additions and 3 deletions

105
src/list.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef INCLUDED_LIST_H
#define INCLUDED_LIST_H
#include "argcountmacro.h"
#include "base.h"
#include <stdarg.h>
DEFOBJTYPE(Cons, CONS, CONSP, {
LispVal *car;
LispVal *cdr;
});
static ALWAYS_INLINE bool LISTP(LispVal *obj) {
return NILP(obj) || CONSP(obj);
}
static ALWAYS_INLINE LispVal *CONS(LispVal *car, LispVal *cdr) {
LispCons *obj = (LispCons *) lisp_alloc_object(sizeof(LispCons), TYPE_CONS);
obj->car = car;
obj->cdr = cdr;
return obj;
}
static ALWAYS_INLINE LispVal *XCAR(LispVal *cons) {
assert(CONSP(cons) || NILP(cons));
return NILP(cons) ? Qnil : ((LispCons *) cons)->car;
}
static ALWAYS_INLINE LispVal *XCDR(LispVal *cons) {
assert(CONSP(cons) || NILP(cons));
return NILP(cons) ? Qnil : ((LispCons *) cons)->cdr;
}
static ALWAYS_INLINE LispVal *XCAR_SAFE(LispVal *cons) {
return CONSP(cons) ? XCAR(cons) : Qnil;
}
static ALWAYS_INLINE LispVal *XCDR_SAFE(LispVal *cons) {
return CONSP(cons) ? XCDR(cons) : Qnil;
}
static ALWAYS_INLINE void RPLACA(LispVal *cons, LispVal *newcar) {
assert(CONSP(cons));
((LispCons *) cons)->car = newcar;
}
static ALWAYS_INLINE void RPLACD(LispVal *cons, LispVal *newcdr) {
assert(CONSP(cons));
((LispCons *) cons)->cdr = newcdr;
}
static ALWAYS_INLINE LispVal *LIST1(LispVal *v1) {
return CONS(v1, Qnil);
}
static ALWAYS_INLINE LispVal *LIST2(LispVal *v1, LispVal *v2) {
return CONS(v1, LIST1(v2));
}
static ALWAYS_INLINE LispVal *LIST3(LispVal *v1, LispVal *v2, LispVal *v3) {
return CONS(v1, LIST2(v2, v3));
}
static ALWAYS_INLINE LispVal *LIST4(LispVal *v1, LispVal *v2, LispVal *v3,
LispVal *v4) {
return CONS(v1, LIST3(v2, v3, v4));
}
static ALWAYS_INLINE LispVal *LIST5(LispVal *v1, LispVal *v2, LispVal *v3,
LispVal *v4, LispVal *v5) {
return CONS(v1, LIST4(v2, v3, v4, v5));
}
static ALWAYS_INLINE LispVal *LIST6(LispVal *v1, LispVal *v2, LispVal *v3,
LispVal *v4, LispVal *v5, LispVal *v6) {
return CONS(v1, LIST5(v2, v3, v4, v5, v6));
}
static ALWAYS_INLINE LispVal *LIST_N(int count, ...) {
va_list list;
va_start(list, count);
LispVal *acc = Qnil;
LispVal *end;
while (count--) {
LispVal *next = CONS(va_arg(list, LispVal *), Qnil);
if (NILP(acc)) {
acc = next;
end = acc;
} else {
RPLACD(end, next);
end = next;
}
}
va_end(list);
return acc;
}
#define LIST(...) MACRO_CALLN(LIST, __VA_ARGS__)
#define FOREACH(l, v) \
for (LispVal *_tail = (l), *v = XCAR(_tail); !NILP(_tail); \
_tail = XCDR(_tail), v = XCAR(_tail))
#define FOREACH_TAIL(l, v) for (LispVal *v = (l); !NILP(v); v = XCDR_SAFE(v))
intptr_t list_length(LispVal *list);
DECLARE_FUNCTION(cons, (LispVal * car, LispVal *cdr));
DECLARE_FUNCTION(length, (LispVal * list));
#endif