2005-02-04 15:39:11 +00:00
|
|
|
/*
|
2007-02-03 10:52:36 +00:00
|
|
|
* $Id: eval.c,v 1.24 2007-02-03 10:51:52 bacon Exp $
|
|
|
|
*
|
|
|
|
* {License}
|
2005-02-04 15:39:11 +00:00
|
|
|
*/
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
#include <ase/lsp/lsp_i.h>
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-11-02 11:10:49 +00:00
|
|
|
static ase_lsp_obj_t* __eval (ase_lsp_t* lsp, ase_lsp_obj_t* obj);
|
2006-10-24 04:22:40 +00:00
|
|
|
static ase_lsp_obj_t* make_func (
|
|
|
|
ase_lsp_t* lsp, ase_lsp_obj_t* cdr, int is_macro);
|
|
|
|
static ase_lsp_obj_t* eval_cons (
|
|
|
|
ase_lsp_t* lsp, ase_lsp_obj_t* cons);
|
|
|
|
static ase_lsp_obj_t* apply (
|
|
|
|
ase_lsp_t* lsp, ase_lsp_obj_t* func, ase_lsp_obj_t* actual);
|
2006-10-29 13:40:33 +00:00
|
|
|
static ase_lsp_obj_t* apply_to_prim (
|
|
|
|
ase_lsp_t* lsp, ase_lsp_obj_t* func, ase_lsp_obj_t* actual);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_obj_t* ase_lsp_eval (ase_lsp_t* lsp, ase_lsp_obj_t* obj)
|
2006-11-02 11:10:49 +00:00
|
|
|
{
|
|
|
|
ase_lsp_obj_t* ret;
|
|
|
|
|
|
|
|
//push_to_eval_stack (obj);
|
|
|
|
|
|
|
|
ret = __eval (lsp, obj);
|
|
|
|
//pop ();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ase_lsp_obj_t* __eval (ase_lsp_t* lsp, ase_lsp_obj_t* obj)
|
2005-02-04 15:39:11 +00:00
|
|
|
{
|
2006-10-26 08:17:38 +00:00
|
|
|
lsp->errnum = ASE_LSP_ENOERR;
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
if (ASE_LSP_TYPE(obj) == ASE_LSP_OBJ_CONS)
|
2006-10-29 13:00:39 +00:00
|
|
|
{
|
2005-02-04 15:39:11 +00:00
|
|
|
return eval_cons (lsp, obj);
|
2006-10-29 13:00:39 +00:00
|
|
|
}
|
|
|
|
else if (ASE_LSP_TYPE(obj) == ASE_LSP_OBJ_SYM)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_assoc_t* assoc;
|
2005-02-04 15:39:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
if (obj == lsp->mem->lambda || obj == lsp->mem->macro) {
|
|
|
|
printf ("lambda or macro can't be used as a normal symbol\n");
|
2007-02-03 10:52:36 +00:00
|
|
|
lsp->errnum = ASE_LSP_EBADSYM;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
assoc = ase_lsp_lookup(lsp->mem, obj);
|
2006-10-29 13:00:39 +00:00
|
|
|
if (assoc == ASE_NULL || assoc->value == ASE_NULL)
|
|
|
|
{
|
|
|
|
if (lsp->opt_undef_symbol)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
lsp->errnum = ASE_LSP_ERR_UNDEF_SYMBOL;
|
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
return lsp->mem->nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = assoc->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
static ase_lsp_obj_t* make_func (ase_lsp_t* lsp, ase_lsp_obj_t* cdr, int is_macro)
|
2005-02-04 15:39:11 +00:00
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_obj_t* func, * formal, * body, * p;
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-29 13:00:39 +00:00
|
|
|
if (cdr == lsp->mem->nil)
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGFEW;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-29 13:00:39 +00:00
|
|
|
if (ASE_LSP_TYPE(cdr) != ASE_LSP_OBJ_CONS)
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGBAD;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
formal = ASE_LSP_CAR(cdr);
|
|
|
|
body = ASE_LSP_CDR(cdr);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-29 13:00:39 +00:00
|
|
|
if (body == lsp->mem->nil)
|
|
|
|
{
|
2007-02-03 10:52:36 +00:00
|
|
|
lsp->errnum = ASE_LSP_EEMPBDY;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2005-09-20 08:05:32 +00:00
|
|
|
// TODO: more lambda expression syntax checks required???.
|
|
|
|
|
|
|
|
/* check if the lambda express has non-nil value
|
|
|
|
* at the terminating cdr */
|
2006-10-24 04:22:40 +00:00
|
|
|
for (p = body; ASE_LSP_TYPE(p) == ASE_LSP_OBJ_CONS; p = ASE_LSP_CDR(p));
|
2006-10-29 13:00:39 +00:00
|
|
|
if (p != lsp->mem->nil)
|
|
|
|
{
|
2005-09-20 08:05:32 +00:00
|
|
|
/* like in (lambda (x) (+ x 10) . 4) */
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGBAD;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-09-19 16:13:18 +00:00
|
|
|
}
|
|
|
|
|
2005-02-04 15:39:11 +00:00
|
|
|
func = (is_macro)?
|
2006-10-25 13:42:31 +00:00
|
|
|
ase_lsp_makemacro (lsp->mem, formal, body):
|
|
|
|
ase_lsp_makefunc (lsp->mem, formal, body);
|
2006-10-29 13:00:39 +00:00
|
|
|
if (func == ASE_NULL)
|
|
|
|
{
|
2006-10-26 08:17:38 +00:00
|
|
|
lsp->errnum = ASE_LSP_ENOMEM;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return func;
|
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
static ase_lsp_obj_t* eval_cons (ase_lsp_t* lsp, ase_lsp_obj_t* cons)
|
2005-02-04 15:39:11 +00:00
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_obj_t* car, * cdr;
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-26 09:31:28 +00:00
|
|
|
ASE_LSP_ASSERT (lsp, ASE_LSP_TYPE(cons) == ASE_LSP_OBJ_CONS);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
car = ASE_LSP_CAR(cons);
|
|
|
|
cdr = ASE_LSP_CDR(cons);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-25 13:42:31 +00:00
|
|
|
if (car == lsp->mem->lambda)
|
|
|
|
{
|
2006-10-29 13:00:39 +00:00
|
|
|
/* (lambda (x) (+ x 20)) */
|
2005-02-04 15:39:11 +00:00
|
|
|
return make_func (lsp, cdr, 0);
|
|
|
|
}
|
2006-10-25 13:42:31 +00:00
|
|
|
else if (car == lsp->mem->macro)
|
|
|
|
{
|
2006-10-29 13:00:39 +00:00
|
|
|
/* (macro (x) (+ x 20)) */
|
2005-02-04 15:39:11 +00:00
|
|
|
return make_func (lsp, cdr, 1);
|
|
|
|
}
|
2006-10-25 13:42:31 +00:00
|
|
|
else if (ASE_LSP_TYPE(car) == ASE_LSP_OBJ_SYM)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_assoc_t* assoc;
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-25 13:42:31 +00:00
|
|
|
if ((assoc = ase_lsp_lookup(lsp->mem, car)) != ASE_NULL)
|
|
|
|
{
|
2006-10-29 13:00:39 +00:00
|
|
|
/*ase_lsp_obj_t* func = assoc->value;*/
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_obj_t* func = assoc->func;
|
2006-10-29 13:00:39 +00:00
|
|
|
if (func == ASE_NULL)
|
|
|
|
{
|
2005-09-20 09:17:06 +00:00
|
|
|
/* the symbol's function definition is void */
|
2006-10-24 04:22:40 +00:00
|
|
|
lsp->errnum = ASE_LSP_ERR_UNDEF_FUNC;
|
|
|
|
return ASE_NULL;
|
2005-09-20 09:17:06 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
if (ASE_LSP_TYPE(func) == ASE_LSP_OBJ_FUNC ||
|
2006-10-25 13:42:31 +00:00
|
|
|
ASE_LSP_TYPE(func) == ASE_LSP_OBJ_MACRO)
|
|
|
|
{
|
2005-02-04 15:39:11 +00:00
|
|
|
return apply (lsp, func, cdr);
|
|
|
|
}
|
2006-10-25 13:42:31 +00:00
|
|
|
else if (ASE_LSP_TYPE(func) == ASE_LSP_OBJ_PRIM)
|
|
|
|
{
|
2005-09-20 12:06:51 +00:00
|
|
|
/* primitive function */
|
2006-10-29 13:40:33 +00:00
|
|
|
return apply_to_prim (lsp, func, cdr);
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
2006-10-25 13:42:31 +00:00
|
|
|
else
|
|
|
|
{
|
2005-09-20 08:05:32 +00:00
|
|
|
//TODO: emit the name for debugging
|
2006-10-24 04:22:40 +00:00
|
|
|
lsp->errnum = ASE_LSP_ERR_UNDEF_FUNC;
|
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//TODO: better error handling.
|
2005-09-20 08:05:32 +00:00
|
|
|
//TODO: emit the name for debugging
|
2006-10-24 04:22:40 +00:00
|
|
|
lsp->errnum = ASE_LSP_ERR_UNDEF_FUNC;
|
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-24 04:22:40 +00:00
|
|
|
else if (ASE_LSP_TYPE(car) == ASE_LSP_OBJ_FUNC ||
|
2006-10-29 13:00:39 +00:00
|
|
|
ASE_LSP_TYPE(car) == ASE_LSP_OBJ_MACRO)
|
|
|
|
{
|
2005-02-04 15:39:11 +00:00
|
|
|
return apply (lsp, car, cdr);
|
|
|
|
}
|
2006-10-29 13:00:39 +00:00
|
|
|
else if (ASE_LSP_TYPE(car) == ASE_LSP_OBJ_CONS)
|
|
|
|
{
|
|
|
|
/* anonymous function or macros
|
|
|
|
* ((lambda (x) (+ x 10)) 50) */
|
|
|
|
if (ASE_LSP_CAR(car) == lsp->mem->lambda)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_obj_t* func = make_func (lsp, ASE_LSP_CDR(car), 0);
|
|
|
|
if (func == ASE_NULL) return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
return apply (lsp, func, cdr);
|
|
|
|
}
|
2006-10-29 13:00:39 +00:00
|
|
|
else if (ASE_LSP_CAR(car) == lsp->mem->macro)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_obj_t* func = make_func (lsp, ASE_LSP_CDR(car), 1);
|
|
|
|
if (func == ASE_NULL) return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
return apply (lsp, func, cdr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-20 08:05:32 +00:00
|
|
|
//TODO: emit the name for debugging
|
2006-10-24 04:22:40 +00:00
|
|
|
lsp->errnum = ASE_LSP_ERR_BAD_FUNC;
|
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
static ase_lsp_obj_t* apply (
|
|
|
|
ase_lsp_t* lsp, ase_lsp_obj_t* func, ase_lsp_obj_t* actual)
|
2005-02-04 15:39:11 +00:00
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
ase_lsp_frame_t* frame;
|
|
|
|
ase_lsp_obj_t* formal;
|
|
|
|
ase_lsp_obj_t* body;
|
|
|
|
ase_lsp_obj_t* value;
|
|
|
|
ase_lsp_mem_t* mem;
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-26 09:31:28 +00:00
|
|
|
ASE_LSP_ASSERT (lsp,
|
2006-10-24 04:22:40 +00:00
|
|
|
ASE_LSP_TYPE(func) == ASE_LSP_OBJ_FUNC ||
|
|
|
|
ASE_LSP_TYPE(func) == ASE_LSP_OBJ_MACRO);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-26 09:31:28 +00:00
|
|
|
ASE_LSP_ASSERT (lsp,
|
2006-10-26 08:17:38 +00:00
|
|
|
ASE_LSP_TYPE(ASE_LSP_CDR(func)) == ASE_LSP_OBJ_CONS);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
|
|
|
mem = lsp->mem;
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
if (ASE_LSP_TYPE(func) == ASE_LSP_OBJ_MACRO)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
formal = ASE_LSP_MFORMAL (func);
|
|
|
|
body = ASE_LSP_MBODY (func);
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
2006-10-26 08:17:38 +00:00
|
|
|
else
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
formal = ASE_LSP_FFORMAL (func);
|
|
|
|
body = ASE_LSP_FBODY (func);
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
/* make a new frame. */
|
|
|
|
frame = ase_lsp_newframe (lsp);
|
|
|
|
if (frame == ASE_NULL)
|
|
|
|
{
|
|
|
|
lsp->errnum = ASE_LSP_ENOMEM;
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
/* attach it to the brooding frame list to
|
2006-11-02 10:30:28 +00:00
|
|
|
* prevent them from begin garbage-collected. */
|
2005-02-04 15:39:11 +00:00
|
|
|
frame->link = mem->brooding_frame;
|
|
|
|
mem->brooding_frame = frame;
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
/* evaluate arguments and push them into the frame. */
|
|
|
|
while (formal != mem->nil)
|
|
|
|
{
|
|
|
|
if (actual == mem->nil)
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGFEW;
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
value = ASE_LSP_CAR(actual);
|
2006-10-26 08:17:38 +00:00
|
|
|
if (ASE_LSP_TYPE(func) != ASE_LSP_OBJ_MACRO)
|
|
|
|
{
|
2006-11-02 10:30:28 +00:00
|
|
|
/* macro doesn't evaluate actual arguments. */
|
2006-10-24 04:22:40 +00:00
|
|
|
value = ase_lsp_eval (lsp, value);
|
2006-10-26 08:17:38 +00:00
|
|
|
if (value == ASE_NULL)
|
|
|
|
{
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
if (ase_lsp_lookupinframe (
|
|
|
|
lsp, frame, ASE_LSP_CAR(formal)) != ASE_NULL)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
lsp->errnum = ASE_LSP_ERR_DUP_FORMAL;
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
2005-09-20 08:05:32 +00:00
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
if (ase_lsp_insertvalueintoframe (
|
|
|
|
lsp, frame, ASE_LSP_CAR(formal), value) == ASE_NULL)
|
|
|
|
{
|
|
|
|
lsp->errnum = ASE_LSP_ENOMEM;
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-24 04:22:40 +00:00
|
|
|
actual = ASE_LSP_CDR(actual);
|
|
|
|
formal = ASE_LSP_CDR(formal);
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
if (ASE_LSP_TYPE(actual) == ASE_LSP_OBJ_CONS)
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGMANY;
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
2006-10-26 08:17:38 +00:00
|
|
|
else if (actual != mem->nil)
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGBAD;
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-11-02 10:30:28 +00:00
|
|
|
/* push the frame */
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->brooding_frame = frame->link;
|
|
|
|
frame->link = mem->frame;
|
|
|
|
mem->frame = frame;
|
|
|
|
|
2006-11-02 10:30:28 +00:00
|
|
|
/* do the evaluation of the body */
|
2005-02-04 15:39:11 +00:00
|
|
|
value = mem->nil;
|
2006-10-26 08:17:38 +00:00
|
|
|
while (body != mem->nil)
|
|
|
|
{
|
2006-10-24 04:22:40 +00:00
|
|
|
value = ase_lsp_eval(lsp, ASE_LSP_CAR(body));
|
2006-10-26 08:17:38 +00:00
|
|
|
if (value == ASE_NULL)
|
|
|
|
{
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->frame = frame->link;
|
2006-10-26 08:17:38 +00:00
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2006-10-24 04:22:40 +00:00
|
|
|
return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
2006-10-24 04:22:40 +00:00
|
|
|
body = ASE_LSP_CDR(body);
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
/* pop the frame. */
|
2005-02-04 15:39:11 +00:00
|
|
|
mem->frame = frame->link;
|
|
|
|
|
2006-10-26 08:17:38 +00:00
|
|
|
/* destroy the frame. */
|
|
|
|
ase_lsp_freeframe (lsp, frame);
|
2005-02-04 15:39:11 +00:00
|
|
|
|
2006-10-29 13:00:39 +00:00
|
|
|
/*if (ASE_LSP_CAR(func) == mem->macro) {*/
|
2006-10-26 08:17:38 +00:00
|
|
|
if (ASE_LSP_TYPE(func) == ASE_LSP_OBJ_MACRO)
|
|
|
|
{
|
2006-11-02 10:30:28 +00:00
|
|
|
value = ase_lsp_eval (lsp, value);
|
2006-10-24 04:22:40 +00:00
|
|
|
if (value == ASE_NULL) return ASE_NULL;
|
2005-02-04 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2006-10-29 13:40:33 +00:00
|
|
|
static ase_lsp_obj_t* apply_to_prim (
|
|
|
|
ase_lsp_t* lsp, ase_lsp_obj_t* func, ase_lsp_obj_t* actual)
|
|
|
|
{
|
|
|
|
ase_lsp_obj_t* obj;
|
|
|
|
ase_size_t count = 0;
|
|
|
|
|
|
|
|
ASE_LSP_ASSERT (lsp, ASE_LSP_TYPE(func) == ASE_LSP_OBJ_PRIM);
|
|
|
|
|
|
|
|
obj = actual;
|
|
|
|
while (ASE_LSP_TYPE(obj) == ASE_LSP_OBJ_CONS)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
obj = ASE_LSP_CDR(obj);
|
|
|
|
}
|
|
|
|
if (obj != lsp->mem->nil)
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGBAD;
|
2006-10-29 13:40:33 +00:00
|
|
|
return ASE_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count < ASE_LSP_PMINARGS(func))
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGFEW;
|
2006-10-29 13:40:33 +00:00
|
|
|
return ASE_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count > ASE_LSP_PMAXARGS(func))
|
|
|
|
{
|
2006-10-30 03:34:41 +00:00
|
|
|
lsp->errnum = ASE_LSP_EARGMANY;
|
2006-10-29 13:40:33 +00:00
|
|
|
return ASE_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ASE_LSP_PIMPL(func) (lsp, actual);
|
|
|
|
}
|