native-funs for data structures

This commit is contained in:
~keith 2021-09-28 18:53:30 -04:00
parent 27401372af
commit a80c932c06
8 changed files with 269 additions and 87 deletions

View File

@ -6,5 +6,6 @@ categories:
- [Arithmetic](stdlib_arithmetic.md)
- [Boolean Logic](stdlib_boolean.md)
- [Comparison](stdlib_comparison.md)
- [Data Structures](stdlib_data.md)
- [Miscellaneous Functions](stdlib_misc.md)
- [Keithlisp Internals](stdlib_internals.md)

47
doc/stdlib_data.md Normal file
View File

@ -0,0 +1,47 @@
# Data Structures
These functions operate on various data structures in Keithlisp.
## `cons`
```
(cons car cdr)
```
`cons` allocates and returns a new cons with the given `car` and `cdr`.
## `car`
```
(car cons)
```
`car` returns the `car` portion of `cons`, or nil if the argument is not
a cons.
## `cdr`
```
(cdr cons)
```
`cdr` returns the `cdr` portion of `cons`, or nil if the argument is not
a cons.
## `list`
```
(list &rest elements)
```
`list` allocates and returns a new list containing `elements`.
## `length`
```
(length list)
```
`length` returns the length of `list`, or nil if it is not a valid list.
If `list` is circular, `length` may never return.
## `nth`
```
(nth index list)
```
Returns the `index`th element in `list`. `index` must be an int.
## `nthcdr`
```
(nthcdr index list)
```
Returns the cdr of the `index`th cons in `list`. `index` must be an int.

View File

@ -24,9 +24,23 @@ interpreted as a signed 2's-complement integer.
creates the association if it does not already exist. It then returns
`value`.
## `unset!`
```
(unset! atom)
```
`unset` deletes the topmost entry for `atom` in the syms-alist, and
returns the value `atom` previously held.
## `fun`
```
(fun atom)
```
`fun` returns the function associated with `atom` in the funs-alist, or
nil if no such function exists.
## `print`
```
(print &rest values)
```
`print` outputs each of its arguments to standard output, separated by
spaces and followed by a newline.

View File

@ -1,6 +1,8 @@
#ifndef _LISP_TYPES_H
#define _LISP_TYPES_H
#include <stdbool.h>
#define LISP_T_CONS 0
#define LISP_T_ATOM 1
#define LISP_T_INT 2
@ -24,6 +26,7 @@ struct lisp_value {
lisp_native_fun funptr;
} value;
char type;
bool gc;
} __attribute__((packed));
struct lisp_cons {

29
main.c
View File

@ -134,11 +134,11 @@ lisp_cons* lisp_alist_del(lisp_cons** alist, lisp_value key) {
return NULL;
}
void test_print_value(lisp_value value) {
void print_value(lisp_value value) {
if (lisp_is_nil(value))
printf("nil");
else if (value.type == LISP_T_CONS)
test_print_cons(value.value.cons);
print_cons(value.value.cons);
else if (value.type == LISP_T_ATOM) {
#ifdef LISP_USE_ATOMS_ALIST
lisp_cons* pair = lisp_alist_get(atoms_alist, value);
@ -158,17 +158,17 @@ void test_print_value(lisp_value value) {
} else if (value.type == LISP_T_FUNPTR)
printf("<native-fun %p>", value.value.funptr);
}
void test_print_cons(lisp_cons* cons) {
void print_cons(lisp_cons* cons) {
printf("(");
while (cons != NULL) {
test_print_value(cons->car);
print_value(cons->car);
if (cons->cdr.type == LISP_T_CONS) {
cons = cons->cdr.value.cons;
if (cons != NULL)
printf(" ");
} else {
printf(" . ");
test_print_value(cons->cdr);
print_value(cons->cdr);
cons = NULL;
}
}
@ -372,42 +372,43 @@ int main() {
init_native_funs();
printf("Init: %4liB used\n", dbg_malloc_mem_usage);
size_t init_mem_usage = dbg_malloc_mem_usage;
printf("Init: %4liB used\n", init_mem_usage);
while (true) {
lisp_cons* tokens = NULL;
lisp_value value;
printf("> ");
printf("%4liB> ", dbg_malloc_mem_usage-init_mem_usage);
lisp_tokenize_init();
if (lisp_parse_recursive(&tokens, &fetch_tokens, &value)) {
//test_print_value(value);
//printf("\n");
lisp_value result;
lisp_evaluate_value(value, &result);
test_print_value(result);
print_value(result);
printf("\n");
printf("Freeing sexpr...\n");
//printf("Freeing sexpr...\n");
if (value.type == LISP_T_CONS)
recursive_free(value.value.cons);
else if (value.type == LISP_T_STRING)
dbg_free(value.value.string);
printf("Freeing tokens...\n");
//printf("Freeing tokens...\n");
recursive_free(tokens);
if (lisp_is_nil(value))
break;
} else {
printf("PARSE ERROR!\n");
test_print_cons(tokens);
print_cons(tokens);
printf("\n");
}
}
printf("Freeing syms-alist...\n");
//printf("Freeing syms-alist...\n");
recursive_free(syms_alist);
printf("Freeing funs-alist...\n");
//printf("Freeing funs-alist...\n");
recursive_free(funs_alist);
printf("Freeing atoms-alist...\n");
//printf("Freeing atoms-alist...\n");
recursive_free(atoms_alist);
printf("Done: %4liB used (should be 0)\n", dbg_malloc_mem_usage);
printf("Peak: %4liB used\n", dbg_malloc_peak_usage);

4
main.h
View File

@ -50,8 +50,8 @@ lisp_cons* lisp_alist_get(lisp_cons* alist, lisp_value key);
lisp_cons* lisp_alist_put(lisp_cons** alist, lisp_cons* pair);
lisp_cons* lisp_alist_del(lisp_cons** alist, lisp_value key);
void test_print_cons(lisp_cons* cons);
void test_print_value(lisp_value value);
void print_cons(lisp_cons* cons);
void print_value(lisp_value value);
lisp_atom lisp_defun_native(lisp_string* lstr, lisp_native_fun funptr);

View File

@ -1,6 +1,6 @@
#include "native_funs.h"
void lisp_add(lisp_cons* cons, lisp_value* value) {
void lispf_add(lisp_cons* cons, lisp_value* value) {
long _int = 0;
float _float = 0.0f;
bool is_float = false;
@ -29,7 +29,7 @@ void lisp_add(lisp_cons* cons, lisp_value* value) {
value->value._int = _int;
}
}
void lisp_sub(lisp_cons* cons, lisp_value* value) {
void lispf_sub(lisp_cons* cons, lisp_value* value) {
long _int = 0;
float _float = 0.0f;
bool is_float = false;
@ -82,7 +82,7 @@ void lisp_sub(lisp_cons* cons, lisp_value* value) {
value->value._int = _int;
}
}
void lisp_mul(lisp_cons* cons, lisp_value* value) {
void lispf_mul(lisp_cons* cons, lisp_value* value) {
long _int = 1;
float _float = 1;
bool is_float = false;
@ -111,7 +111,7 @@ void lisp_mul(lisp_cons* cons, lisp_value* value) {
value->value._int = _int;
}
}
void lisp_div(lisp_cons* cons, lisp_value* value) {
void lispf_div(lisp_cons* cons, lisp_value* value) {
float _float = 0;
if (cons->car.type == LISP_T_FLOAT)
@ -135,7 +135,7 @@ void lisp_div(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_FLOAT;
value->value._float = _float;
}
void lisp_intdiv(lisp_cons* cons, lisp_value* value) {
void lispf_intdiv(lisp_cons* cons, lisp_value* value) {
long _int = 0;
if (cons->car.type == LISP_T_FLOAT)
@ -160,7 +160,7 @@ void lisp_intdiv(lisp_cons* cons, lisp_value* value) {
value->value._int = _int;
}
void lisp_not(lisp_cons* cons, lisp_value* value) {
void lispf_not(lisp_cons* cons, lisp_value* value) {
if (lisp_is_nil(cons->car)) {
value->type = LISP_T_ATOM;
value->value.atom = atom_t;
@ -169,7 +169,7 @@ void lisp_not(lisp_cons* cons, lisp_value* value) {
value->value.cons = NULL;
}
}
void lisp_or(lisp_cons* cons, lisp_value* value) {
void lispf_or(lisp_cons* cons, lisp_value* value) {
while (cons != NULL) {
if (!lisp_is_nil(cons->car)) {
*value = cons->car;
@ -180,7 +180,7 @@ void lisp_or(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_CONS;
value->value.cons = NULL;
}
void lisp_and(lisp_cons* cons, lisp_value* value) {
void lispf_and(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_CONS;
value->value.cons = NULL;
while (cons != NULL) {
@ -191,7 +191,7 @@ void lisp_and(lisp_cons* cons, lisp_value* value) {
}
}
void lisp_eq(lisp_cons* cons, lisp_value* value) {
void lispf_eq(lisp_cons* cons, lisp_value* value) {
lisp_value cmp_value = cons->car;
cons = cons->cdr.value.cons;
while (cons != NULL) {
@ -205,7 +205,7 @@ void lisp_eq(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_ATOM;
value->value.atom = atom_t;
}
void lisp_num_eq(lisp_cons* cons, lisp_value* value) {
void lispf_num_eq(lisp_cons* cons, lisp_value* value) {
lisp_value cmp_value = cons->car;
if (cmp_value.type != LISP_T_INT && cmp_value.type != LISP_T_FLOAT) {
value->type = LISP_T_CONS;
@ -235,7 +235,7 @@ void lisp_num_eq(lisp_cons* cons, lisp_value* value) {
}
*value = cmp_value;
}
void lisp_num_lt(lisp_cons* cons, lisp_value* value) {
void lispf_num_lt(lisp_cons* cons, lisp_value* value) {
lisp_value cmp_value = cons->car;
if (cmp_value.type != LISP_T_INT && cmp_value.type != LISP_T_FLOAT) {
value->type = LISP_T_CONS;
@ -266,7 +266,7 @@ void lisp_num_lt(lisp_cons* cons, lisp_value* value) {
}
*value = cmp_value;
}
void lisp_num_gt(lisp_cons* cons, lisp_value* value) {
void lispf_num_gt(lisp_cons* cons, lisp_value* value) {
lisp_value cmp_value = cons->car;
if (cmp_value.type != LISP_T_INT && cmp_value.type != LISP_T_FLOAT) {
value->type = LISP_T_CONS;
@ -297,7 +297,7 @@ void lisp_num_gt(lisp_cons* cons, lisp_value* value) {
}
*value = cmp_value;
}
void lisp_num_le(lisp_cons* cons, lisp_value* value) {
void lispf_num_le(lisp_cons* cons, lisp_value* value) {
lisp_value cmp_value = cons->car;
if (cmp_value.type != LISP_T_INT && cmp_value.type != LISP_T_FLOAT) {
value->type = LISP_T_CONS;
@ -328,7 +328,7 @@ void lisp_num_le(lisp_cons* cons, lisp_value* value) {
}
*value = cmp_value;
}
void lisp_num_ge(lisp_cons* cons, lisp_value* value) {
void lispf_num_ge(lisp_cons* cons, lisp_value* value) {
lisp_value cmp_value = cons->car;
if (cmp_value.type != LISP_T_INT && cmp_value.type != LISP_T_FLOAT) {
value->type = LISP_T_CONS;
@ -360,10 +360,87 @@ void lisp_num_ge(lisp_cons* cons, lisp_value* value) {
*value = cmp_value;
}
void lisp_type_of(lisp_cons* cons, lisp_value* value) {
void lispf_cons(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_CONS;
value->value.cons = dbg_malloc(sizeof(lisp_cons));
value->value.cons->car = cons->car;
value->value.cons->cdr = cons->cdr.value.cons->car;
}
void lispf_car(lisp_cons* cons, lisp_value* value) {
if (cons->car.type != LISP_T_CONS || lisp_is_nil(cons->car))
return;
*value = cons->car.value.cons->car;
}
void lispf_cdr(lisp_cons* cons, lisp_value* value) {
if (cons->car.type != LISP_T_CONS || lisp_is_nil(cons->car))
return;
*value = cons->car.value.cons->cdr;
}
void lispf_list(lisp_cons* cons, lisp_value* value) {
lisp_cons* head = NULL;
lisp_cons* tail = NULL;
while (cons != NULL) {
lisp_cons* element = dbg_malloc(sizeof(lisp_cons));
element->car = cons->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;
cons = cons->cdr.value.cons;
}
value->type = LISP_T_CONS;
value->value.cons = head;
}
void lispf_length(lisp_cons* cons, lisp_value* value) {
if (cons->car.type != LISP_T_CONS)
return;
lisp_cons* head = cons->car.value.cons;
value->type = LISP_T_INT;
value->value._int = 0;
while (head != NULL) {
value->value._int++;
if (head->cdr.type != LISP_T_CONS)
head = NULL;
else
head = head->cdr.value.cons;
}
}
void lispf_nth(lisp_cons* cons, lisp_value* value) {
if (cons->car.type != LISP_T_INT)
return;
int index = cons->car.value._int;
lisp_cons* head = cons->cdr.value.cons->car.value.cons;
while (index > 0) {
if (head == NULL)
return;
head = head->cdr.value.cons;
index--;
}
*value = head->car;
}
void lispf_nthcdr(lisp_cons* cons, lisp_value* value) {
if (cons->car.type != LISP_T_INT)
return;
int index = cons->car.value._int;
lisp_cons* head = cons->cdr.value.cons->car.value.cons;
while (index > 0) {
if (head == NULL)
return;
head = head->cdr.value.cons;
index--;
}
*value = head->cdr;
}
void lispf_type_of(lisp_cons* cons, lisp_value* value) {
if (lisp_is_nil(cons->car)) {
value->type = LISP_T_CONS;
value->value.cons = NULL;
return;
}
value->type = LISP_T_ATOM;
@ -389,12 +466,12 @@ void lisp_type_of(lisp_cons* cons, lisp_value* value) {
}
}
void lisp_addr_of(lisp_cons* cons, lisp_value* value) {
void lispf_addr_of(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_INT;
value->value._int = (long) cons->car.value.cons;
}
void lisp_set(lisp_cons* cons, lisp_value* value) {
void lispf_set(lisp_cons* cons, lisp_value* value) {
// extract key and value
lisp_value key = cons->car;
*value = cons->cdr.value.cons->car;
@ -415,61 +492,90 @@ void lisp_set(lisp_cons* cons, lisp_value* value) {
new_alist->cdr.type = LISP_T_CONS;
new_alist->cdr.value.cons = syms_alist;
syms_alist = new_alist;
return;
}
void lisp_fun(lisp_cons* cons, lisp_value* value) {
lisp_cons* pair = lisp_alist_get(funs_alist, cons->car);
if (pair == NULL) {
value->type = LISP_T_CONS;
value->value.cons = NULL;
void lispf_unset(lisp_cons* cons, lisp_value* value) {
lisp_cons* pair = lisp_alist_del(&syms_alist, cons->car);
if (pair == NULL)
return;
*value = pair->cdr;
dbg_free(pair);
}
void lispf_fun(lisp_cons* cons, lisp_value* value) {
lisp_cons* pair = lisp_alist_get(funs_alist, cons->car);
if (pair == NULL)
return;
}
*value = pair->cdr;
}
void lisp_internals_syms_alist(lisp_cons* cons, lisp_value* value) {
void lispf_print(lisp_cons* cons, lisp_value* value) {
while (cons != NULL) {
if (cons->car.type == LISP_T_STRING)
lisp_string_print(cons->car.value.string);
else
print_value(cons->car);
cons = cons->cdr.value.cons;
if (cons != NULL)
printf(" ");
}
printf("\n");
}
void lispf_internals_syms_alist(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_CONS;
value->value.cons = syms_alist;
}
void lisp_internals_funs_alist(lisp_cons* cons, lisp_value* value) {
void lispf_internals_funs_alist(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_CONS;
value->value.cons = funs_alist;
}
void lisp_internals_atoms_alist(lisp_cons* cons, lisp_value* value) {
void lispf_internals_atoms_alist(lisp_cons* cons, lisp_value* value) {
value->type = LISP_T_CONS;
value->value.cons = atoms_alist;
}
void init_native_funs() {
// arithmetic
lisp_defun_native(lisp_string_create("+"), &lisp_add);
lisp_defun_native(lisp_string_create("-"), &lisp_sub);
lisp_defun_native(lisp_string_create("*"), &lisp_mul);
lisp_defun_native(lisp_string_create("/"), &lisp_div);
lisp_defun_native(lisp_string_create("int/"), &lisp_intdiv);
lisp_defun_native(lisp_string_create("+"), &lispf_add);
lisp_defun_native(lisp_string_create("-"), &lispf_sub);
lisp_defun_native(lisp_string_create("*"), &lispf_mul);
lisp_defun_native(lisp_string_create("/"), &lispf_div);
lisp_defun_native(lisp_string_create("int/"), &lispf_intdiv);
// boolean logic
lisp_defun_native(lisp_string_create("not"), &lisp_not);
lisp_defun_native(lisp_string_create("or"), &lisp_or);
lisp_defun_native(lisp_string_create("and"), &lisp_and);
lisp_defun_native(lisp_string_create("not"), &lispf_not);
lisp_defun_native(lisp_string_create("or"), &lispf_or);
lisp_defun_native(lisp_string_create("and"), &lispf_and);
// comparison
lisp_defun_native(lisp_string_create("eq"), &lisp_eq);
lisp_defun_native(lisp_string_create("="), &lisp_num_eq);
lisp_defun_native(lisp_string_create("<"), &lisp_num_lt);
lisp_defun_native(lisp_string_create(">"), &lisp_num_gt);
lisp_defun_native(lisp_string_create("<="), &lisp_num_le);
lisp_defun_native(lisp_string_create(">="), &lisp_num_ge);
lisp_defun_native(lisp_string_create("eq"), &lispf_eq);
lisp_defun_native(lisp_string_create("="), &lispf_num_eq);
lisp_defun_native(lisp_string_create("<"), &lispf_num_lt);
lisp_defun_native(lisp_string_create(">"), &lispf_num_gt);
lisp_defun_native(lisp_string_create("<="), &lispf_num_le);
lisp_defun_native(lisp_string_create(">="), &lispf_num_ge);
// data structures
lisp_defun_native(lisp_string_create("cons"), &lispf_cons);
lisp_defun_native(lisp_string_create("car"), &lispf_car);
lisp_defun_native(lisp_string_create("cdr"), &lispf_cdr);
lisp_defun_native(lisp_string_create("list"), &lispf_list);
lisp_defun_native(lisp_string_create("length"), &lispf_length);
lisp_defun_native(lisp_string_create("nth"), &lispf_nth);
lisp_defun_native(lisp_string_create("nthcdr"), &lispf_nthcdr);
// etc
lisp_defun_native(lisp_string_create("type-of"), &lisp_type_of);
lisp_defun_native(lisp_string_create("addr-of"), &lisp_addr_of);
lisp_defun_native(lisp_string_create("set"), &lisp_set);
lisp_defun_native(lisp_string_create("fun"), &lisp_fun);
lisp_defun_native(lisp_string_create("type-of"), &lispf_type_of);
lisp_defun_native(lisp_string_create("addr-of"), &lispf_addr_of);
lisp_defun_native(lisp_string_create("set"), &lispf_set);
lisp_defun_native(lisp_string_create("unset!"), &lispf_unset);
lisp_defun_native(lisp_string_create("fun"), &lispf_fun);
lisp_defun_native(lisp_string_create("print"), &lispf_print);
// internals
lisp_defun_native(lisp_string_create("syms-alist!"), &lisp_internals_syms_alist);
lisp_defun_native(lisp_string_create("funs-alist!"), &lisp_internals_funs_alist);
lisp_defun_native(lisp_string_create("atoms-alist!"), &lisp_internals_atoms_alist);
lisp_defun_native(lisp_string_create("syms-alist!"), &lispf_internals_syms_alist);
lisp_defun_native(lisp_string_create("funs-alist!"), &lispf_internals_funs_alist);
lisp_defun_native(lisp_string_create("atoms-alist!"), &lispf_internals_atoms_alist);
}

View File

@ -8,31 +8,41 @@
#include "lisp_string.h"
#include "main.h"
void lisp_add(lisp_cons* cons, lisp_value* value);
void lisp_sub(lisp_cons* cons, lisp_value* value);
void lisp_mul(lisp_cons* cons, lisp_value* value);
void lisp_div(lisp_cons* cons, lisp_value* value);
void lisp_intdiv(lisp_cons* cons, lisp_value* value);
void lispf_add(lisp_cons* cons, lisp_value* value);
void lispf_sub(lisp_cons* cons, lisp_value* value);
void lispf_mul(lisp_cons* cons, lisp_value* value);
void lispf_div(lisp_cons* cons, lisp_value* value);
void lispf_intdiv(lisp_cons* cons, lisp_value* value);
void lisp_not(lisp_cons* cons, lisp_value* value);
void lisp_or(lisp_cons* cons, lisp_value* value);
void lisp_and(lisp_cons* cons, lisp_value* value);
void lispf_not(lisp_cons* cons, lisp_value* value);
void lispf_or(lisp_cons* cons, lisp_value* value);
void lispf_and(lisp_cons* cons, lisp_value* value);
void lisp_eq(lisp_cons* cons, lisp_value* value);
void lisp_num_eq(lisp_cons* cons, lisp_value* value);
void lisp_num_lt(lisp_cons* cons, lisp_value* value);
void lisp_num_gt(lisp_cons* cons, lisp_value* value);
void lisp_num_le(lisp_cons* cons, lisp_value* value);
void lisp_num_ge(lisp_cons* cons, lisp_value* value);
void lispf_eq(lisp_cons* cons, lisp_value* value);
void lispf_num_eq(lisp_cons* cons, lisp_value* value);
void lispf_num_lt(lisp_cons* cons, lisp_value* value);
void lispf_num_gt(lisp_cons* cons, lisp_value* value);
void lispf_num_le(lisp_cons* cons, lisp_value* value);
void lispf_num_ge(lisp_cons* cons, lisp_value* value);
void lisp_type_of(lisp_cons* cons, lisp_value* value);
void lisp_addr_of(lisp_cons* cons, lisp_value* value);
void lisp_set(lisp_cons* cons, lisp_value* value);
void lisp_fun(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_cdr(lisp_cons* cons, lisp_value* value);
void lisp_internals_syms_alist(lisp_cons* cons, lisp_value* value);
void lisp_internals_funs_alist(lisp_cons* cons, lisp_value* value);
void lisp_internals_atoms_alist(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_nth(lisp_cons* cons, lisp_value* value);
void lispf_nthcdr(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_set(lisp_cons* cons, lisp_value* value);
void lispf_fun(lisp_cons* cons, lisp_value* value);
void lispf_print(lisp_cons* cons, lisp_value* value);
void lispf_internals_syms_alist(lisp_cons* cons, lisp_value* value);
void lispf_internals_funs_alist(lisp_cons* cons, lisp_value* value);
void lispf_internals_atoms_alist(lisp_cons* cons, lisp_value* value);
void init_native_funs();
#endif