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:
parent
cb3128d241
commit
19db4bb6b2
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
25
src/cont.c
25
src/cont.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue