Exceptions!!!

This commit is contained in:
2026-09-02 01:54:14 -07:00
parent 17c11d90ea
commit 07060a17fe
13 changed files with 396 additions and 60 deletions
+39 -6
View File
@@ -1,6 +1,10 @@
#include "list.h"
#include "function.h"
#include "stack.h"
DEFINE_SYMBOL(circular_list_error, "circular-list-error");
DEFINE_CONDITION_CLASS(circular_list_error, error);
intptr_t list_length(LispVal *list) {
assert(LISTP(list));
@@ -32,21 +36,24 @@ DEFUN(cons, "cons", (LispVal * car, LispVal *cdr), "(car cdr)",
}
DEFUN(length, "length", (LispVal * list), "(list)", "") {
// TODO type check
// TODO list may be circular
return MAKE_FIXNUM(list_length(list));
CHECK_LISTP(list);
intptr_t len = list_length(list);
if (len == -1) {
lisp_signal(Qcircular_list_error, Qnil);
}
return MAKE_FIXNUM(len);
}
DEFUN(length_eq, "length=", (LispVal * list, LispVal *length), "(list length)",
"Return non-nil if LIST's length is LENGTH.") {
// TODO type check
CHECK_LISTP(list);
return list_length_eq(list, XFIXNUM(length)) ? Qt : Qnil;
}
DEFUN(nreverse, "nreverse", (LispVal * list), "(list)", "") {
// TODO type checking
LispVal *rev = Qnil;
while (!NILP(list)) {
CHECK_LISTP(list);
LispVal *next = XCDR(list);
RPLACD(list, rev);
rev = list;
@@ -63,6 +70,22 @@ DEFUN(list, "list", (LispVal * args), "(&rest args)", "") {
return args;
}
LispVal *nth(size_t n, LispVal *list) {
size_t i = 0;
DOTAILS(rest, list) {
if (i == n) {
return XCAR(rest);
}
++i;
}
return Qnil;
}
DEFUN(nth, "list", (LispVal * n, LispVal *list), "(n list)", "") {
CHECK_TYPE(n, TYPE_FIXNUM);
return nth(XFIXNUM(n), list);
}
DEFUN(member, "member", (LispVal * elt, LispVal *list, LispVal *pred),
"(elt list &optional pred)", "") {
if (NILP(pred) || pred == Qeq) {
@@ -74,7 +97,7 @@ DEFUN(member, "member", (LispVal * elt, LispVal *list, LispVal *pred),
}
} else {
DOTAILS(rest, list) {
if (CALL(pred, elt, XCAR(rest))) {
if (!NILP(CALL(pred, elt, XCAR(rest)))) {
return rest;
}
}
@@ -82,6 +105,16 @@ DEFUN(member, "member", (LispVal * elt, LispVal *list, LispVal *pred),
return Qnil;
}
DEFUN(member_if, "member-if", (LispVal * pred, LispVal *list), "(pred list)",
"") {
DOTAILS(rest, list) {
if (!NILP(CALL(pred, XCAR(rest)))) {
return rest;
}
}
return Qnil;
}
DEFUN(plist_put, "plist-put", (LispVal * plist, LispVal *prop, LispVal *value),
"(plist prop value)", "") {
CHECK_LISTP(plist);