support rest arguments
This commit is contained in:
parent
40a2568142
commit
f3041b7ebc
|
@ -49,6 +49,7 @@ struct pic_irep {
|
||||||
struct pic_code *code;
|
struct pic_code *code;
|
||||||
size_t clen, ccapa;
|
size_t clen, ccapa;
|
||||||
int argc;
|
int argc;
|
||||||
|
bool varg;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,8 +13,10 @@ typedef struct codegen_scope {
|
||||||
|
|
||||||
/* local variables are 1-indexed */
|
/* local variables are 1-indexed */
|
||||||
struct xhash *local_tbl;
|
struct xhash *local_tbl;
|
||||||
|
/* does not count rest argument variable */
|
||||||
size_t argc;
|
size_t argc;
|
||||||
int *cv_tbl;
|
int *cv_tbl;
|
||||||
|
bool varg;
|
||||||
} codegen_scope;
|
} codegen_scope;
|
||||||
|
|
||||||
static codegen_scope *
|
static codegen_scope *
|
||||||
|
@ -27,6 +29,7 @@ new_global_scope(pic_state *pic)
|
||||||
scope->local_tbl = pic->global_tbl;
|
scope->local_tbl = pic->global_tbl;
|
||||||
scope->argc = -1;
|
scope->argc = -1;
|
||||||
scope->cv_tbl = NULL;
|
scope->cv_tbl = NULL;
|
||||||
|
scope->varg = false;
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,14 +44,25 @@ new_local_scope(pic_state *pic, pic_value args, codegen_scope *scope)
|
||||||
new_scope = (codegen_scope *)pic_alloc(pic, sizeof(codegen_scope));
|
new_scope = (codegen_scope *)pic_alloc(pic, sizeof(codegen_scope));
|
||||||
new_scope->up = scope;
|
new_scope->up = scope;
|
||||||
new_scope->local_tbl = x = xh_new();
|
new_scope->local_tbl = x = xh_new();
|
||||||
|
new_scope->varg = false;
|
||||||
|
|
||||||
i = 1;
|
i = 1;
|
||||||
for (v = args; ! pic_nil_p(v); v = pic_cdr(pic, v)) {
|
for (v = args; pic_pair_p(v); v = pic_cdr(pic, v)) {
|
||||||
pic_value sym;
|
pic_value sym;
|
||||||
|
|
||||||
sym = pic_car(pic, v);
|
sym = pic_car(pic, v);
|
||||||
xh_put(x, pic_symbol_ptr(sym)->name, i++);
|
xh_put(x, pic_symbol_ptr(sym)->name, i++);
|
||||||
}
|
}
|
||||||
|
if (pic_nil_p(v)) {
|
||||||
|
/* pass */
|
||||||
|
}
|
||||||
|
else if (pic_symbol_p(v)) {
|
||||||
|
new_scope->varg = true;
|
||||||
|
xh_put(x, pic_symbol_ptr(v)->name, i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pic_error(pic, "logic flaw");
|
||||||
|
}
|
||||||
new_scope->argc = i;
|
new_scope->argc = i;
|
||||||
new_scope->cv_tbl = (int *)pic_calloc(pic, i, sizeof(int));
|
new_scope->cv_tbl = (int *)pic_calloc(pic, i, sizeof(int));
|
||||||
|
|
||||||
|
@ -75,6 +89,7 @@ new_irep(pic_state *pic)
|
||||||
irep->clen = 0;
|
irep->clen = 0;
|
||||||
irep->ccapa = 1024;
|
irep->ccapa = 1024;
|
||||||
irep->argc = -1;
|
irep->argc = -1;
|
||||||
|
irep->varg = false;
|
||||||
return irep;
|
return irep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,9 +561,6 @@ codegen_lambda(codegen_state *state, pic_value obj)
|
||||||
if (! valid_formal(pic, args)) {
|
if (! valid_formal(pic, args)) {
|
||||||
pic_error(pic, "syntax error");
|
pic_error(pic, "syntax error");
|
||||||
}
|
}
|
||||||
if (! pic_list_p(pic, args)) {
|
|
||||||
pic_error(pic, "variable-length argument not supported (for now)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* inner environment */
|
/* inner environment */
|
||||||
prev_irep = state->irep;
|
prev_irep = state->irep;
|
||||||
|
@ -557,6 +569,7 @@ codegen_lambda(codegen_state *state, pic_value obj)
|
||||||
state->scope = new_local_scope(pic, args, state->scope);
|
state->scope = new_local_scope(pic, args, state->scope);
|
||||||
state->irep = irep = new_irep(pic);
|
state->irep = irep = new_irep(pic);
|
||||||
irep->argc = state->scope->argc;
|
irep->argc = state->scope->argc;
|
||||||
|
irep->varg = state->scope->varg;
|
||||||
{
|
{
|
||||||
/* body */
|
/* body */
|
||||||
body = pic_cdr(pic, pic_cdr(pic, obj));
|
body = pic_cdr(pic, pic_cdr(pic, obj));
|
||||||
|
|
10
src/vm.c
10
src/vm.c
|
@ -245,11 +245,21 @@ pic_run(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i;
|
int i;
|
||||||
|
pic_value rest;
|
||||||
|
|
||||||
if (ci->argc != proc->u.irep->argc) {
|
if (ci->argc != proc->u.irep->argc) {
|
||||||
|
if (! (proc->u.irep->varg && ci->argc >= proc->u.irep->argc)) {
|
||||||
pic->errmsg = "wrong number of arguments";
|
pic->errmsg = "wrong number of arguments";
|
||||||
goto L_RAISE;
|
goto L_RAISE;
|
||||||
}
|
}
|
||||||
|
/* prepare rest args */
|
||||||
|
rest = pic_nil_value();
|
||||||
|
for (i = 0; i < ci->argc - proc->u.irep->argc; ++i) {
|
||||||
|
pic_gc_protect(pic, v = POP());
|
||||||
|
rest = pic_cons(pic, v, rest);
|
||||||
|
}
|
||||||
|
PUSH(rest);
|
||||||
|
}
|
||||||
for (i = 0; i < proc->u.irep->argc; ++i) {
|
for (i = 0; i < proc->u.irep->argc; ++i) {
|
||||||
proc->env->values[i] = ci->fp[i];
|
proc->env->values[i] = ci->fp[i];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue