summaryrefslogtreecommitdiff
path: root/lisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lisp.c')
-rw-r--r--lisp.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/lisp.c b/lisp.c
index da0a5f6..5f5a6fb 100644
--- a/lisp.c
+++ b/lisp.c
@@ -35,10 +35,13 @@ value *make_string(const char *s) {
return val;
}
+value *NIL = NULL;
value *make_nil() {
- value *val = malloc(sizeof(value));
- val->type = VT_NIL;
- return val;
+ if (!NIL) {
+ NIL = malloc(sizeof(value));
+ NIL->type = VT_NIL;
+ }
+ return NIL;
}
value *make_lambda(env *e, value *params, value *body) {
@@ -312,6 +315,46 @@ value *builtin_isnull(env *e, value *args) {
return make_nil();
}
+int value_eq(value *a, value *b) {
+ if(a->type != b->type){
+ return 0;
+ }
+ if(a == b){
+ return 1;
+ }
+ switch (a->type) {
+ case VT_INT: return a->as.i == b->as.i;
+ case VT_DOUBLE: return a->as.d == b->as.d;
+ case VT_SYMBOL: return !strcmp(a->as.sym, b->as.sym);
+ case VT_STRING: return !strcmp(a->as.sym, b->as.sym);
+ case VT_NIL: return 1;
+ case VT_PAIR:
+ return value_eq(car(a), car(b)) &&
+ value_eq(cdr(a), cdr(b));
+ case VT_LAMBDA:
+ case VT_BUILTIN:
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+value *builtin_eq(env *e, value *args) {
+ value *v_prev = eval(e, car(args));
+
+ args = cdr(args);
+ while (args->type == VT_PAIR) {
+ value *v_cur = eval(e, car(args));
+ if (!value_eq(v_prev, v_cur)) {
+ return make_nil();
+ }
+ v_prev = v_cur;
+ args = cdr(args);
+ }
+
+ return make_int(1);
+}
+
value *apply_to_nums(env *e, value *args, double (*fn)(double, double)) {
double result;
value *v = eval(e, car(args));