diff --git a/functions.c b/functions.c index 3a109e0..fa0318d 100644 --- a/functions.c +++ b/functions.c @@ -56,10 +56,7 @@ lval* builtin_pow(lenv* env, lval* val){ lval* builtin_op(lenv* env, lval* val, char* op) { //Ensure numbers only for(int i = 0; i < val->cell_count; i++) { - if (val->cell_list[i]->type != LVAL_NUM) { - lval_delete(val); - return lval_err(LERR_BAD_NUM); - } + LASSERT_TYPE(op, val, val->cell_list[i], LVAL_NUM); } //Get the first element @@ -78,10 +75,10 @@ lval* builtin_op(lenv* env, lval* val, char* op) { if (strcmp(op, "*") == 0) { x->data.num *= y->data.num; } if (strcmp(op, "^") == 0) { x->data.num = pow(x->data.num,y->data.num); } if (strcmp(op, "/") == 0) { - int zero = 0; - if (y->type == LVAL_NUM && fabs(y->data.num) <= DBL_EPSILON) {zero = 1;} + short divZero = 0; + if (y->type == LVAL_NUM && fabs(y->data.num) <= DBL_EPSILON) {divZero = 1;} - if (zero) { + if (divZero) { lval_delete(x); lval_delete(y); x = lval_err(LERR_DIV_ZERO); @@ -124,8 +121,8 @@ lval* builtin_join(lenv* env, lval* val){ return x; } lval* builtin_head(lenv* env, lval* val){ - LASSERT_ARG_COUNT("head",val , val, 1); - LASSERT_TYPE("head",val , val->cell_list[0], LVAL_Q_EXPR); + LASSERT_ARG_COUNT("head", val, val, 1); + LASSERT_TYPE("head", val, val->cell_list[0], LVAL_Q_EXPR); LASSERT_MIN_ARG_COUNT("head", val, val->cell_list[0], 1); lval* x = lval_take(val, 0); @@ -202,16 +199,22 @@ lval* builtin_lambda(lenv* env, lval* val) { LASSERT_TYPE("lambda", val, val->cell_list[1], LVAL_Q_EXPR); lval* symbols = val->cell_list[0]; + lval* va = NULL; for(int i = 0; i < symbols->cell_count; i++) { LASSERT_TYPE("lambda args", val, symbols->cell_list[i], LVAL_SYM); + if (strcmp("&", symbols->cell_list[i]->data.sym) == 0 && i+1 == symbols->cell_count) { + va = lval_pop(symbols, i); + break; + } } - lval* formals = lval_pop(val,0); + lval* formals = lval_pop(val, 0); lval* body = lval_pop(val, 0); body->type = LVAL_S_EXPR; lval* lambda = lval_lambda(formals, body); + lambda->data.func->va = va; lval_delete(val); return lambda; } \ No newline at end of file diff --git a/lval.c b/lval.c index 7997b63..1c2dabd 100644 --- a/lval.c +++ b/lval.c @@ -113,10 +113,21 @@ lval* lval_call(lenv* env, lval* function, lval* args) { LASSERT(args, func->formals->cell_count <= args->cell_count, LERR_SYNTAX, "lambda: insufficient arguments. Expected %ld got %ld", func->formals->cell_count, args->cell_count); - for(int i = 0; i < args->cell_count; i++) { + for(int i = 0; i < func->formals->cell_count; i++) { lenv_put(func->env, func->formals->cell_list[i], args->cell_list[i]); } + if (func->va != NULL) { + lval* vaArgs = lval_q_expr(); + + for(int i = func->formals->cell_count; i < args->cell_count; i ++ ) { + lval_add(vaArgs, lval_copy(args->cell_list[i])); + } + + lenv_put(func->env, func->va, vaArgs); + lval_delete(vaArgs); + } + lval_delete(args); func->env->parent = env; diff --git a/lval.h b/lval.h index d6cff86..ce164ce 100644 --- a/lval.h +++ b/lval.h @@ -34,6 +34,7 @@ struct lval_func { lenv* env; lval* formals; lval* body; + lval* va; }; struct lval { diff --git a/nbproject/Makefile-impl.mk b/nbproject/Makefile-impl.mk index 5b25bd3..f2cf699 100644 --- a/nbproject/Makefile-impl.mk +++ b/nbproject/Makefile-impl.mk @@ -24,7 +24,7 @@ CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} # Project Name -PROJECTNAME=KLisp +PROJECTNAME=klisp # Active Configuration DEFAULTCONF=Debug