-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Description
Hi,
have had a lot of fun hacking with your lisp(s)! What I missed where default values/expressions for parameters so I made something myself, maybe usefull, use it if you like it. As a consequence there is no error message anymore for not enough actual parameters , any remaining parameters are bounded to nil/empty list or default value, which is quite usefull to prevent some 'helper' functions. See below the relevant part of the eval function (from closure to macro) which I have changed (have declared cv and cx variables at the top)
else if (T(*f) == CLOS) { /* if f is a closure, then */
*d = cdr(*f); /* construct an extended local environment d from f's static scope */
if (T(*d) == NIL) /* if f's static scope is nil, then use global env as static scope */
*d = env;
v = car(car(*f)); /* get the parameters v of closure f */
while (T(v) == CONS && T(x) == CONS) { /* bind parameters v to argument values x to extend the local scope d */
cv = car(v); /* to check if parameter is a list with default value*/
if (T(cv) == CONS){ /* check if parameter has a default */
cx = eval(car(x),e);
/* if argument is not nil then bind it else bind default value*/
*d = pair(car(car(v)), !not(cx) ? cx : eval(car(cdr(car(v))), e), *d);
}
else
*d = pair(car(v), eval(car(x),e), *d); /* add new binding to the front of d */
v = cdr(v);
x = cdr(x);
}
if (T(v) == CONS) { /* continue binding v if x is after a dot (... . x) by evaluating x */
*y = eval(x, e); /* evaluate x and save its value y to protect it from getting GC'ed */
while (T(v) == CONS && T(*y) == CONS) {
*d = pair(car(v), car(*y), *d); /* add new binding to the front of d */
v = cdr(v);
*y = cdr(*y);
}
while (T(v) == CONS){ /* no more actual arguments, bind remaining parameters to nil or default*/
cv=car(v);
if (T(cv) == CONS) /* check if parameter has default value*/
*d = pair(car(car(v)), eval(car(cdr(car(v))),e), *d);
else
*d = pair(car(v), nil, *d);
v=cdr(v);
}
x = *y;
}
else if (T(x) == CONS) /* if more arguments x are provided then evaluate them all */
x = evlis(x, e);
else if (T(x) != NIL) /* else if last argument x is after a dot (... . x) then evaluate x */
x = eval(x, e);
if (T(v) != NIL) /* if last parameter v is after a dot (... . v) then bind it to x */
*d = pair(v, x, *d);
x = *y = cdr(car(*f)); /* tail recursion optimization: evaluate the body x of closure f next */
e = *z = *d; /* the new environment e is d to evaluate x, put in *z to protect */
}
else if (T(*f) == MACR) { /* else if f is a macro, then */
*d = env; /* construct an extended local environment d from global env */
v = car(*f); /* get the parameters v of macro f */
while (T(v) == CONS && T(x) == CONS) { /* bind parameters v to arguments x to extend the local scope d */
cv=car(v); /* if no more actual arguments bind remaining parameters to nil or default*/
if (T(cv) == CONS) /* check to see if default values */
*d = pair(car(cv), !not(car(x)) ? car(x) : car(cdr(cv)), *d);
else
*d = pair(car(v), car(x), *d);
v = cdr(v);
x = cdr(x);
}
while (T(v)== CONS) { /* if no more actual arguments bind remaining parameters to nil or default*/
cv=car(v);
if (T(cv) == CONS) /* check if parameter has default value, if so bind against if car(x) is nil */
*d = pair(car(cv), car(cdr(cv)), *d);
else
*d = pair(car(v), nil, *d);
v = cdr(v);
}
if (T(v) != NIL) /* if last parameter v is after a dot (... . v) then bind it to x */
*d = pair(v, x, *d);
x = *y = eval(cdr(*f), *d); /* evaluated body of the macro to evaluate next, put in *z to protect */
}
Tests:
4112+7740>(def test (a (b 1) (c 2) . d) (println a b c d ))
test
4080+7734>(test)
()12()
()
4080+7734>(test 1 2)
122()
()
4080+7734>(test 1 2 3)
123()
()
4080+7734>(test 1 2 3 4 5 6)
123(4 5 6)
()
4080+7734>(test 1 () 3 4 5 6)
113(4 5 6)
()
Robert-van-Engelen
Metadata
Metadata
Assignees
Labels
No labels