diff options
| author | Keith Packard <keithp@keithp.com> | 2016-11-15 20:21:47 -0800 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2017-02-20 11:16:51 -0800 | 
| commit | 1a00bf4ac12a6505d4b23d94e99b4b46bf679020 (patch) | |
| tree | 184001cfb70289eb0b951d76354ee3becb3db1e7 /src/lisp/ao_lisp_lambda.c | |
| parent | 5c1fa73f159de9d9839e8619494c26931521d2d4 (diff) | |
altos/lisp: Allow macro/nlambda/lexpr to have multiple args
Entries from the params are bound to the formals with whatever
remaining formals there are bound to the last argument as a list.
This makes writing functions a bit easier.
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/lisp/ao_lisp_lambda.c')
| -rw-r--r-- | src/lisp/ao_lisp_lambda.c | 36 | 
1 files changed, 22 insertions, 14 deletions
| diff --git a/src/lisp/ao_lisp_lambda.c b/src/lisp/ao_lisp_lambda.c index 8b761714..186236f6 100644 --- a/src/lisp/ao_lisp_lambda.c +++ b/src/lisp/ao_lisp_lambda.c @@ -134,6 +134,8 @@ ao_lisp_lambda_eval(void)  	struct ao_lisp_frame	*next_frame;  	int			args_wanted;  	int			args_provided; +	int			f; +	struct ao_lisp_cons	*vals  	DBGI("lambda "); DBG_POLY(ao_lisp_lambda_poly(lambda)); DBG("\n"); @@ -141,12 +143,14 @@ ao_lisp_lambda_eval(void)  	/* Create a frame to hold the variables  	 */ -	if (lambda->args == AO_LISP_FUNC_LAMBDA) -		args_provided = ao_lisp_cons_length(cons) - 1; -	else -		args_provided = 1; -	if (args_wanted != args_provided) -		return ao_lisp_error(AO_LISP_INVALID, "need %d args, not %d", args_wanted, args_provided); +	args_provided = ao_lisp_cons_length(cons) - 1; +	if (lambda->args == AO_LISP_FUNC_LAMBDA) { +		if (args_wanted != args_provided) +			return ao_lisp_error(AO_LISP_INVALID, "need %d args, got %d", args_wanted, args_provided); +	} else { +		if (args_provided < args_wanted - 1) +			return ao_lisp_error(AO_LISP_INVALID, "need at least %d args, got %d", args_wanted, args_provided); +	}  	next_frame = ao_lisp_frame_new(args_wanted); @@ -155,12 +159,10 @@ ao_lisp_lambda_eval(void)  	cons = ao_lisp_poly_cons(ao_lisp_stack->values);  	code = ao_lisp_poly_cons(lambda->code);  	args = ao_lisp_poly_cons(ao_lisp_arg(code, 0)); +	vals = ao_lisp_poly_cons(cons->cdr);  	switch (lambda->args) { -	case AO_LISP_FUNC_LAMBDA: { -		int			f; -		struct ao_lisp_cons	*vals = ao_lisp_poly_cons(cons->cdr); - +	case AO_LISP_FUNC_LAMBDA:  		for (f = 0; f < args_wanted; f++) {  			DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(vals->car); DBG("\n");  			next_frame->vals[f].atom = args->car; @@ -170,13 +172,19 @@ ao_lisp_lambda_eval(void)  		}  		ao_lisp_cons_free(cons);  		break; -	}  	case AO_LISP_FUNC_LEXPR:  	case AO_LISP_FUNC_NLAMBDA:  	case AO_LISP_FUNC_MACRO: -		DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(cons->cdr); DBG("\n"); -		next_frame->vals[0].atom = args->car; -		next_frame->vals[0].val = cons->cdr; +		for (f = 0; f < args_wanted - 1; f++) { +			DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(vals->car); DBG("\n"); +			next_frame->vals[f].atom = args->car; +			next_frame->vals[f].val = vals->car; +			args = ao_lisp_poly_cons(args->cdr); +			vals = ao_lisp_poly_cons(vals->cdr); +		} +		DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(); DBG("\n"); +		next_frame->vals[f].atom = args->car; +		next_frame->vals[f].val = ao_lisp_cons_poly(vals);  		break;  	}  	next_frame->prev = lambda->frame; | 
