rest array got by pic_get_args has a dynamic extent; that is, we cannot

store it to a heap object when we are going to rewind that stack and
restore an old continuation.
This commit is contained in:
Yuichi Nishiwaki 2014-02-02 12:27:48 +09:00
parent cb3128d241
commit 19db4bb6b2
3 changed files with 22 additions and 11 deletions

View File

@ -30,8 +30,7 @@ struct pic_cont {
struct pic_object *arena[PIC_ARENA_SIZE]; struct pic_object *arena[PIC_ARENA_SIZE];
int arena_idx; int arena_idx;
size_t argc; pic_value results;
pic_value *argv;
}; };
#define PIC_BLK_INCREF(pic,blk) do { \ #define PIC_BLK_INCREF(pic,blk) do { \
@ -54,6 +53,7 @@ struct pic_cont {
pic_value pic_callcc(pic_state *, struct pic_proc *); pic_value pic_callcc(pic_state *, struct pic_proc *);
pic_value pic_values(pic_state *, size_t, ...); pic_value pic_values(pic_state *, size_t, ...);
pic_value pic_values_by_array(pic_state *, size_t, pic_value *); pic_value pic_values_by_array(pic_state *, size_t, pic_value *);
pic_value pic_values_by_list(pic_state *, pic_value);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -9,6 +9,7 @@
#include "picrin.h" #include "picrin.h"
#include "picrin/proc.h" #include "picrin/proc.h"
#include "picrin/cont.h" #include "picrin/cont.h"
#include "picrin/pair.h"
static void save_cont(pic_state *, struct pic_cont **); static void save_cont(pic_state *, struct pic_cont **);
static void restore_cont(pic_state *, struct pic_cont *); static void restore_cont(pic_state *, struct pic_cont *);
@ -61,8 +62,7 @@ save_cont(pic_state *pic, struct pic_cont **c)
cont->arena_idx = pic->arena_idx; cont->arena_idx = pic->arena_idx;
memcpy(cont->arena, pic->arena, sizeof(struct pic_object *) * PIC_ARENA_SIZE); memcpy(cont->arena, pic->arena, sizeof(struct pic_object *) * PIC_ARENA_SIZE);
cont->argc = 0; cont->results = pic_undef_value();
cont->argv = NULL;
} }
static void static void
@ -142,8 +142,7 @@ cont_call(pic_state *pic)
pic_get_args(pic, "*", &argc, &argv); pic_get_args(pic, "*", &argc, &argv);
cont = (struct pic_cont *)pic_ptr(proc->env->values[0]); cont = (struct pic_cont *)pic_ptr(proc->env->values[0]);
cont->argc = argc; cont->results = pic_list_by_array(pic, argc, argv);
cont->argv = argv;
/* execute guard handlers */ /* execute guard handlers */
walk_to_block(pic, pic->blk, cont->blk); walk_to_block(pic, pic->blk, cont->blk);
@ -158,8 +157,7 @@ pic_callcc(pic_state *pic, struct pic_proc *proc)
save_cont(pic, &cont); save_cont(pic, &cont);
if (setjmp(cont->jmp)) { if (setjmp(cont->jmp)) {
printf("%d\n", cont->argc); return pic_values_by_list(pic, cont->results);
return pic_values_from_array(pic, cont->argc, cont->argv);
} }
else { else {
struct pic_proc *c; struct pic_proc *c;
@ -205,6 +203,21 @@ pic_values_by_array(pic_state *pic, size_t argc, pic_value *argv)
return argc == 0 ? pic_none_value() : pic->ci->fp[0]; return argc == 0 ? pic_none_value() : pic->ci->fp[0];
} }
pic_value
pic_values_by_list(pic_state *pic, pic_value list)
{
pic_value v;
size_t i;
i = 0;
pic_for_each (v, list) {
pic->ci->fp[i++] = v;
}
pic->ci->fp[i] = pic_undef_value();
return pic_nil_p(list) ? pic_none_value() : pic->ci->fp[0];
}
static pic_value static pic_value
pic_cont_callcc(pic_state *pic) pic_cont_callcc(pic_state *pic)
{ {

View File

@ -386,9 +386,7 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
} }
/* result values */ /* result values */
for (i = 0; i < cont->argc; ++i) { gc_mark(pic, cont->results);
gc_mark(pic, cont->argv[i]);
}
break; break;
} }
case PIC_TT_SYNTAX: { case PIC_TT_SYNTAX: {