more data type functions
This commit is contained in:
parent
a80c932c06
commit
e1fc25eebc
|
@ -11,15 +11,29 @@ These functions operate on various data structures in Keithlisp.
|
||||||
```
|
```
|
||||||
(car cons)
|
(car cons)
|
||||||
```
|
```
|
||||||
`car` returns the `car` portion of `cons`, or nil if the argument is not
|
`car` returns the car portion of `cons`, or nil if the argument is not a
|
||||||
a cons.
|
cons.
|
||||||
|
|
||||||
## `cdr`
|
## `cdr`
|
||||||
```
|
```
|
||||||
(cdr cons)
|
(cdr cons)
|
||||||
```
|
```
|
||||||
`cdr` returns the `cdr` portion of `cons`, or nil if the argument is not
|
`cdr` returns the cdr portion of `cons`, or nil if the argument is not a
|
||||||
a cons.
|
cons.
|
||||||
|
|
||||||
|
## `rplaca`
|
||||||
|
```
|
||||||
|
(rplaca cons value)
|
||||||
|
```
|
||||||
|
`rplaca` changes the car portion of `cons` to `value`. It returns the
|
||||||
|
same `cons` it was given.
|
||||||
|
|
||||||
|
## `rplacd`
|
||||||
|
```
|
||||||
|
(rplacd cons value)
|
||||||
|
```
|
||||||
|
`rplacd` changes the cdr portion of `cons` to `value`. It returns the
|
||||||
|
same `cons` it was given.
|
||||||
|
|
||||||
## `list`
|
## `list`
|
||||||
```
|
```
|
||||||
|
@ -32,16 +46,63 @@ a cons.
|
||||||
(length list)
|
(length list)
|
||||||
```
|
```
|
||||||
`length` returns the length of `list`, or nil if it is not a valid list.
|
`length` returns the length of `list`, or nil if it is not a valid list.
|
||||||
If `list` is circular, `length` may never return.
|
**If `list` is circular, `length` will go into an infinite loop.**
|
||||||
|
|
||||||
## `nth`
|
## `nth`
|
||||||
```
|
```
|
||||||
(nth index list)
|
(nth index list)
|
||||||
```
|
```
|
||||||
Returns the `index`th element in `list`. `index` must be an int.
|
`nth` returns the `index`th element in `list`. `index` must be an int.
|
||||||
|
|
||||||
|
If `index` is negative, `nth` will add `(length list)` to it. **This
|
||||||
|
will fail if `list` is circular.**
|
||||||
|
|
||||||
## `nthcdr`
|
## `nthcdr`
|
||||||
```
|
```
|
||||||
(nthcdr index list)
|
(nthcdr index list)
|
||||||
```
|
```
|
||||||
Returns the cdr of the `index`th cons in `list`. `index` must be an int.
|
`nthcdr` returns the cdr of the `index`th cons in `list`. `index` must
|
||||||
|
be an int.
|
||||||
|
|
||||||
|
If `index` is negative, `nthcdr` will add `(length list)` to it. **This
|
||||||
|
will fail if `list` is circular.**
|
||||||
|
|
||||||
|
## `append`
|
||||||
|
```
|
||||||
|
(append &rest lists)
|
||||||
|
```
|
||||||
|
`append` constructs a new list containing all the elements of `lists`
|
||||||
|
appended together. It makes a shallow copy of each of its arguments.
|
||||||
|
|
||||||
|
## `push`
|
||||||
|
```
|
||||||
|
(push list item)
|
||||||
|
```
|
||||||
|
`push` pushes `item` onto `list` and returns the new head of `list`.
|
||||||
|
|
||||||
|
## `assoc`
|
||||||
|
```
|
||||||
|
(assoc alist key)
|
||||||
|
```
|
||||||
|
`assoc` returns the first cons in `alist` whose car is
|
||||||
|
[`eq`](stdlib_comparison.md#eq) to `key`, or nil if no matching cons
|
||||||
|
was found.
|
||||||
|
|
||||||
|
## `rassoc`
|
||||||
|
```
|
||||||
|
(rassoc alist value)
|
||||||
|
```
|
||||||
|
`rassoc` returns the first cons in `alist` whose cdr is
|
||||||
|
[`eq`](stdlib_comparison.md#eq) to `value`, or nil if no matching cons
|
||||||
|
was found.
|
||||||
|
|
||||||
|
## `alist-put`
|
||||||
|
```
|
||||||
|
(alist-put alist key value)
|
||||||
|
```
|
||||||
|
`alist-put` creates a new cons mapping `key` to `value`, and attempts to
|
||||||
|
update `alist` with it in-place. If `alist` already contains a cons
|
||||||
|
whose car is [`eq`](stdlib_comparison.md#eq) to `key`, the cons is
|
||||||
|
replaced in-place with the new one. Otherwise, `alist-put` pushes the
|
||||||
|
new cons onto `alist` and returns the new head of `alist`, in the same
|
||||||
|
manner as [`push`](stdlib_data.md#push).
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct lisp_value {
|
||||||
lisp_native_fun funptr;
|
lisp_native_fun funptr;
|
||||||
} value;
|
} value;
|
||||||
char type;
|
char type;
|
||||||
bool gc;
|
//bool gc;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct lisp_cons {
|
struct lisp_cons {
|
||||||
|
|
120
native_funs.c
120
native_funs.c
|
@ -376,6 +376,18 @@ void lispf_cdr(lisp_cons* cons, lisp_value* value) {
|
||||||
return;
|
return;
|
||||||
*value = cons->car.value.cons->cdr;
|
*value = cons->car.value.cons->cdr;
|
||||||
}
|
}
|
||||||
|
void lispf_rplaca(lisp_cons* cons, lisp_value* value) {
|
||||||
|
if (cons->car.type != LISP_T_CONS || lisp_is_nil(cons->car))
|
||||||
|
return;
|
||||||
|
cons->car.value.cons->car = cons->cdr.value.cons->car;
|
||||||
|
*value = cons->car;
|
||||||
|
}
|
||||||
|
void lispf_rplacd(lisp_cons* cons, lisp_value* value) {
|
||||||
|
if (cons->car.type != LISP_T_CONS || lisp_is_nil(cons->car))
|
||||||
|
return;
|
||||||
|
cons->car.value.cons->cdr = cons->cdr.value.cons->car;
|
||||||
|
*value = cons->car;
|
||||||
|
}
|
||||||
|
|
||||||
void lispf_list(lisp_cons* cons, lisp_value* value) {
|
void lispf_list(lisp_cons* cons, lisp_value* value) {
|
||||||
lisp_cons* head = NULL;
|
lisp_cons* head = NULL;
|
||||||
|
@ -416,11 +428,19 @@ void lispf_nth(lisp_cons* cons, lisp_value* value) {
|
||||||
if (cons->car.type != LISP_T_INT)
|
if (cons->car.type != LISP_T_INT)
|
||||||
return;
|
return;
|
||||||
int index = cons->car.value._int;
|
int index = cons->car.value._int;
|
||||||
|
if (index < 0) {
|
||||||
|
// index is negative, call lispf_length
|
||||||
|
lisp_value temp;
|
||||||
|
lispf_length(cons->cdr.value.cons, &temp);
|
||||||
|
index += temp.value._int;
|
||||||
|
}
|
||||||
lisp_cons* head = cons->cdr.value.cons->car.value.cons;
|
lisp_cons* head = cons->cdr.value.cons->car.value.cons;
|
||||||
|
if (head == NULL)
|
||||||
|
return;
|
||||||
while (index > 0) {
|
while (index > 0) {
|
||||||
|
head = head->cdr.value.cons;
|
||||||
if (head == NULL)
|
if (head == NULL)
|
||||||
return;
|
return;
|
||||||
head = head->cdr.value.cons;
|
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
*value = head->car;
|
*value = head->car;
|
||||||
|
@ -429,14 +449,100 @@ void lispf_nthcdr(lisp_cons* cons, lisp_value* value) {
|
||||||
if (cons->car.type != LISP_T_INT)
|
if (cons->car.type != LISP_T_INT)
|
||||||
return;
|
return;
|
||||||
int index = cons->car.value._int;
|
int index = cons->car.value._int;
|
||||||
|
if (index < 0) {
|
||||||
|
// index is negative, call lispf_length
|
||||||
|
lisp_value temp;
|
||||||
|
lispf_length(cons->cdr.value.cons, &temp);
|
||||||
|
index += temp.value._int;
|
||||||
|
}
|
||||||
lisp_cons* head = cons->cdr.value.cons->car.value.cons;
|
lisp_cons* head = cons->cdr.value.cons->car.value.cons;
|
||||||
|
if (head == NULL)
|
||||||
|
return;
|
||||||
while (index > 0) {
|
while (index > 0) {
|
||||||
|
head = head->cdr.value.cons;
|
||||||
if (head == NULL)
|
if (head == NULL)
|
||||||
return;
|
return;
|
||||||
head = head->cdr.value.cons;
|
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
*value = head->cdr;
|
value->type = LISP_T_CONS;
|
||||||
|
value->value.cons = head;
|
||||||
|
}
|
||||||
|
void lispf_append(lisp_cons* cons, lisp_value* value) {
|
||||||
|
lisp_cons* head = NULL;
|
||||||
|
lisp_cons* tail = NULL;
|
||||||
|
|
||||||
|
while (cons != NULL) {
|
||||||
|
if (cons->cdr.value.cons == NULL && cons->car.type != LISP_T_CONS) {
|
||||||
|
tail->cdr = cons->car;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
lisp_cons* subcons = cons->car.value.cons;
|
||||||
|
while (subcons != NULL) {
|
||||||
|
lisp_cons* element = dbg_malloc(sizeof(lisp_cons));
|
||||||
|
element->car = subcons->car;
|
||||||
|
element->cdr.type = LISP_T_CONS;
|
||||||
|
element->cdr.value.cons = NULL;
|
||||||
|
|
||||||
|
if (head == NULL)
|
||||||
|
head = element;
|
||||||
|
if (tail != NULL)
|
||||||
|
tail->cdr.value.cons = element;
|
||||||
|
|
||||||
|
tail = element;
|
||||||
|
subcons = subcons->cdr.value.cons;
|
||||||
|
}
|
||||||
|
cons = cons->cdr.value.cons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value->type = LISP_T_CONS;
|
||||||
|
value->value.cons = head;
|
||||||
|
}
|
||||||
|
void lispf_push(lisp_cons* cons, lisp_value* value) {
|
||||||
|
lisp_cons* list = cons->car.value.cons;
|
||||||
|
lisp_value item = cons->cdr.value.cons->car;
|
||||||
|
|
||||||
|
value->type = LISP_T_CONS;
|
||||||
|
value->value.cons = dbg_malloc(sizeof(lisp_cons));
|
||||||
|
value->value.cons->car = item;
|
||||||
|
value->value.cons->cdr.type = LISP_T_CONS;
|
||||||
|
value->value.cons->cdr.value.cons = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lispf_assoc(lisp_cons* cons, lisp_value* value) {
|
||||||
|
lisp_cons* alist = cons->car.value.cons;
|
||||||
|
lisp_value key = cons->cdr.value.cons->car;
|
||||||
|
value->type = LISP_T_CONS;
|
||||||
|
value->value.cons = lisp_alist_get(alist, key);
|
||||||
|
}
|
||||||
|
void lispf_rassoc(lisp_cons* cons, lisp_value* value) {
|
||||||
|
lisp_cons* alist = cons->car.value.cons;
|
||||||
|
lisp_value cdr_key = cons->cdr.value.cons->car;
|
||||||
|
value->type = LISP_T_CONS;
|
||||||
|
while (alist != NULL) {
|
||||||
|
if (alist->car.type != LISP_T_CONS || alist->car.value.cons == NULL)
|
||||||
|
goto next;
|
||||||
|
value->value.cons = alist->car.value.cons;
|
||||||
|
if (lisp_is_equal(value->value.cons->cdr, cdr_key))
|
||||||
|
return;
|
||||||
|
next:
|
||||||
|
if (alist->cdr.type == LISP_T_CONS)
|
||||||
|
alist = alist->cdr.value.cons;
|
||||||
|
else
|
||||||
|
alist = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void lispf_alist_put(lisp_cons* cons, lisp_value* value) {
|
||||||
|
value->type = LISP_T_CONS;
|
||||||
|
value->value.cons = cons->car.value.cons;
|
||||||
|
lisp_value key = cons->cdr.value.cons->car;
|
||||||
|
lisp_value new_value = cons->cdr.value.cons->cdr.value.cons->car;
|
||||||
|
|
||||||
|
lisp_cons* pair = dbg_malloc(sizeof(lisp_cons));
|
||||||
|
pair->car = key;
|
||||||
|
pair->cdr = new_value;
|
||||||
|
|
||||||
|
lisp_cons* old_pair = lisp_alist_put(&value->value.cons, pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lispf_type_of(lisp_cons* cons, lisp_value* value) {
|
void lispf_type_of(lisp_cons* cons, lisp_value* value) {
|
||||||
|
@ -560,11 +666,19 @@ void init_native_funs() {
|
||||||
lisp_defun_native(lisp_string_create("cons"), &lispf_cons);
|
lisp_defun_native(lisp_string_create("cons"), &lispf_cons);
|
||||||
lisp_defun_native(lisp_string_create("car"), &lispf_car);
|
lisp_defun_native(lisp_string_create("car"), &lispf_car);
|
||||||
lisp_defun_native(lisp_string_create("cdr"), &lispf_cdr);
|
lisp_defun_native(lisp_string_create("cdr"), &lispf_cdr);
|
||||||
|
lisp_defun_native(lisp_string_create("rplaca"), &lispf_rplaca);
|
||||||
|
lisp_defun_native(lisp_string_create("rplacd"), &lispf_rplacd);
|
||||||
|
|
||||||
lisp_defun_native(lisp_string_create("list"), &lispf_list);
|
lisp_defun_native(lisp_string_create("list"), &lispf_list);
|
||||||
lisp_defun_native(lisp_string_create("length"), &lispf_length);
|
lisp_defun_native(lisp_string_create("length"), &lispf_length);
|
||||||
lisp_defun_native(lisp_string_create("nth"), &lispf_nth);
|
lisp_defun_native(lisp_string_create("nth"), &lispf_nth);
|
||||||
lisp_defun_native(lisp_string_create("nthcdr"), &lispf_nthcdr);
|
lisp_defun_native(lisp_string_create("nthcdr"), &lispf_nthcdr);
|
||||||
|
lisp_defun_native(lisp_string_create("append"), &lispf_append);
|
||||||
|
lisp_defun_native(lisp_string_create("push"), &lispf_push);
|
||||||
|
|
||||||
|
lisp_defun_native(lisp_string_create("assoc"), &lispf_assoc);
|
||||||
|
lisp_defun_native(lisp_string_create("rassoc"), &lispf_rassoc);
|
||||||
|
lisp_defun_native(lisp_string_create("alist-put"), &lispf_alist_put);
|
||||||
|
|
||||||
// etc
|
// etc
|
||||||
lisp_defun_native(lisp_string_create("type-of"), &lispf_type_of);
|
lisp_defun_native(lisp_string_create("type-of"), &lispf_type_of);
|
||||||
|
|
|
@ -28,11 +28,19 @@ void lispf_num_ge(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_cons(lisp_cons* cons, lisp_value* value);
|
void lispf_cons(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_car(lisp_cons* cons, lisp_value* value);
|
void lispf_car(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_cdr(lisp_cons* cons, lisp_value* value);
|
void lispf_cdr(lisp_cons* cons, lisp_value* value);
|
||||||
|
void lispf_rplaca(lisp_cons* cons, lisp_value* value);
|
||||||
|
void lispf_rplacd(lisp_cons* cons, lisp_value* value);
|
||||||
|
|
||||||
void lispf_list(lisp_cons* cons, lisp_value* value);
|
void lispf_list(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_length(lisp_cons* cons, lisp_value* value);
|
void lispf_length(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_nth(lisp_cons* cons, lisp_value* value);
|
void lispf_nth(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_nthcdr(lisp_cons* cons, lisp_value* value);
|
void lispf_nthcdr(lisp_cons* cons, lisp_value* value);
|
||||||
|
void lispf_append(lisp_cons* cons, lisp_value* value);
|
||||||
|
void lispf_push(lisp_cons* cons, lisp_value* value);
|
||||||
|
|
||||||
|
void lispf_assoc(lisp_cons* cons, lisp_value* value);
|
||||||
|
void lispf_rassoc(lisp_cons* cons, lisp_value* value);
|
||||||
|
void lispf_alist_put(lisp_cons* cons, lisp_value* value);
|
||||||
|
|
||||||
void lispf_type_of(lisp_cons* cons, lisp_value* value);
|
void lispf_type_of(lisp_cons* cons, lisp_value* value);
|
||||||
void lispf_addr_of(lisp_cons* cons, lisp_value* value);
|
void lispf_addr_of(lisp_cons* cons, lisp_value* value);
|
||||||
|
|
Loading…
Reference in New Issue