Added variable arguments to lambda functions. Last argument must be '&' to work.
This commit is contained in:
17
functions.c
17
functions.c
@@ -56,10 +56,7 @@ lval* builtin_pow(lenv* env, lval* val){
|
|||||||
lval* builtin_op(lenv* env, lval* val, char* op) {
|
lval* builtin_op(lenv* env, lval* val, char* op) {
|
||||||
//Ensure numbers only
|
//Ensure numbers only
|
||||||
for(int i = 0; i < val->cell_count; i++) {
|
for(int i = 0; i < val->cell_count; i++) {
|
||||||
if (val->cell_list[i]->type != LVAL_NUM) {
|
LASSERT_TYPE(op, val, val->cell_list[i], LVAL_NUM);
|
||||||
lval_delete(val);
|
|
||||||
return lval_err(LERR_BAD_NUM);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the first element
|
//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 *= y->data.num; }
|
||||||
if (strcmp(op, "^") == 0) { x->data.num = pow(x->data.num,y->data.num); }
|
if (strcmp(op, "^") == 0) { x->data.num = pow(x->data.num,y->data.num); }
|
||||||
if (strcmp(op, "/") == 0) {
|
if (strcmp(op, "/") == 0) {
|
||||||
int zero = 0;
|
short divZero = 0;
|
||||||
if (y->type == LVAL_NUM && fabs(y->data.num) <= DBL_EPSILON) {zero = 1;}
|
if (y->type == LVAL_NUM && fabs(y->data.num) <= DBL_EPSILON) {divZero = 1;}
|
||||||
|
|
||||||
if (zero) {
|
if (divZero) {
|
||||||
lval_delete(x);
|
lval_delete(x);
|
||||||
lval_delete(y);
|
lval_delete(y);
|
||||||
x = lval_err(LERR_DIV_ZERO);
|
x = lval_err(LERR_DIV_ZERO);
|
||||||
@@ -202,9 +199,14 @@ lval* builtin_lambda(lenv* env, lval* val) {
|
|||||||
LASSERT_TYPE("lambda", val, val->cell_list[1], LVAL_Q_EXPR);
|
LASSERT_TYPE("lambda", val, val->cell_list[1], LVAL_Q_EXPR);
|
||||||
|
|
||||||
lval* symbols = val->cell_list[0];
|
lval* symbols = val->cell_list[0];
|
||||||
|
lval* va = NULL;
|
||||||
|
|
||||||
for(int i = 0; i < symbols->cell_count; i++) {
|
for(int i = 0; i < symbols->cell_count; i++) {
|
||||||
LASSERT_TYPE("lambda args", val, symbols->cell_list[i], LVAL_SYM);
|
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);
|
||||||
@@ -212,6 +214,7 @@ lval* builtin_lambda(lenv* env, lval* val) {
|
|||||||
body->type = LVAL_S_EXPR;
|
body->type = LVAL_S_EXPR;
|
||||||
|
|
||||||
lval* lambda = lval_lambda(formals, body);
|
lval* lambda = lval_lambda(formals, body);
|
||||||
|
lambda->data.func->va = va;
|
||||||
lval_delete(val);
|
lval_delete(val);
|
||||||
return lambda;
|
return lambda;
|
||||||
}
|
}
|
||||||
13
lval.c
13
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,
|
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);
|
"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]);
|
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);
|
lval_delete(args);
|
||||||
|
|
||||||
func->env->parent = env;
|
func->env->parent = env;
|
||||||
|
|||||||
1
lval.h
1
lval.h
@@ -34,6 +34,7 @@ struct lval_func {
|
|||||||
lenv* env;
|
lenv* env;
|
||||||
lval* formals;
|
lval* formals;
|
||||||
lval* body;
|
lval* body;
|
||||||
|
lval* va;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lval {
|
struct lval {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
|
|||||||
|
|
||||||
|
|
||||||
# Project Name
|
# Project Name
|
||||||
PROJECTNAME=KLisp
|
PROJECTNAME=klisp
|
||||||
|
|
||||||
# Active Configuration
|
# Active Configuration
|
||||||
DEFAULTCONF=Debug
|
DEFAULTCONF=Debug
|
||||||
|
|||||||
Reference in New Issue
Block a user