add pic_closure_ref, pic_closure_set, and pic_lambda
This commit is contained in:
+7
-11
@@ -82,18 +82,20 @@ pic_load_point(pic_state *pic, struct pic_cont *cont)
|
||||
pic->cc = cont->prev;
|
||||
}
|
||||
|
||||
#define CV_ID 0
|
||||
#define CV_ESCAPE 1
|
||||
|
||||
static pic_value
|
||||
cont_call(pic_state *pic)
|
||||
{
|
||||
struct pic_proc *self;
|
||||
int argc;
|
||||
pic_value *argv;
|
||||
int id;
|
||||
struct pic_cont *cc, *cont;
|
||||
|
||||
pic_get_args(pic, "&*", &self, &argc, &argv);
|
||||
pic_get_args(pic, "*", &argc, &argv);
|
||||
|
||||
id = pic_int(pic_proc_env_ref(pic, self, "id"));
|
||||
id = pic_int(pic_closure_ref(pic, CV_ID));
|
||||
|
||||
/* check if continuation is alive */
|
||||
for (cc = pic->cc; cc != NULL; cc = cc->prev) {
|
||||
@@ -105,7 +107,7 @@ cont_call(pic_state *pic)
|
||||
pic_errorf(pic, "calling dead escape continuation");
|
||||
}
|
||||
|
||||
cont = pic_data_ptr(pic_proc_env_ref(pic, self, "escape"))->data;
|
||||
cont = pic_data_ptr(pic_closure_ref(pic, CV_ESCAPE))->data;
|
||||
cont->results = pic_list_by_array(pic, argc, argv);
|
||||
|
||||
pic_load_point(pic, cont);
|
||||
@@ -120,15 +122,9 @@ pic_make_cont(pic_state *pic, struct pic_cont *cont)
|
||||
{
|
||||
static const pic_data_type cont_type = { "cont", NULL, NULL };
|
||||
struct pic_proc *c;
|
||||
struct pic_data *e;
|
||||
|
||||
c = pic_make_proc(pic, cont_call);
|
||||
|
||||
e = pic_data_alloc(pic, &cont_type, cont);
|
||||
|
||||
/* save the escape continuation in proc */
|
||||
pic_proc_env_set(pic, c, "escape", pic_obj_value(e));
|
||||
pic_proc_env_set(pic, c, "id", pic_int_value(cont->id));
|
||||
c = pic_lambda(pic, cont_call, 2, pic_int_value(cont->id), pic_obj_value(pic_data_alloc(pic, &cont_type, cont)));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ pic_native_exception_handler(pic_state *pic)
|
||||
|
||||
pic->err = err;
|
||||
|
||||
cont = pic_proc_ptr(pic_proc_env_ref(pic, self, "cont"));
|
||||
cont = pic_proc_ptr(pic_closure_ref(pic, 0));
|
||||
|
||||
pic_call(pic, cont, 1, pic_false_value());
|
||||
|
||||
|
||||
+3
-2
@@ -302,8 +302,9 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
|
||||
LOOP(obj->u.proc.u.i.cxt);
|
||||
}
|
||||
} else {
|
||||
if (obj->u.proc.u.f.env) {
|
||||
LOOP(obj->u.proc.u.f.env);
|
||||
int i;
|
||||
for (i = 0; i < obj->u.proc.u.f.localc; ++i) {
|
||||
gc_mark(pic, obj->u.proc.locals[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -151,6 +151,8 @@ void pic_defvar(pic_state *, const char *, pic_value, struct pic_proc *);
|
||||
void pic_define(pic_state *, struct pic_lib *, const char *, pic_value);
|
||||
pic_value pic_ref(pic_state *, struct pic_lib *, const char *);
|
||||
void pic_set(pic_state *, struct pic_lib *, const char *, pic_value);
|
||||
pic_value pic_closure_ref(pic_state *, int);
|
||||
void pic_closure_set(pic_state *, int, pic_value);
|
||||
pic_value pic_funcall(pic_state *pic, struct pic_lib *, const char *, int, ...);
|
||||
|
||||
struct pic_lib *pic_make_library(pic_state *, pic_value);
|
||||
@@ -161,13 +163,13 @@ void pic_export(pic_state *, pic_sym *);
|
||||
PIC_NORETURN void pic_panic(pic_state *, const char *);
|
||||
PIC_NORETURN void pic_errorf(pic_state *, const char *, ...);
|
||||
|
||||
struct pic_proc *pic_lambda(pic_state *, pic_func_t, int, ...);
|
||||
struct pic_proc *pic_vlambda(pic_state *, pic_func_t, int, va_list);
|
||||
pic_value pic_call(pic_state *, struct pic_proc *, int, ...);
|
||||
pic_value pic_vcall(pic_state *, struct pic_proc *, int, va_list);
|
||||
pic_value pic_apply(pic_state *, struct pic_proc *, int, pic_value *);
|
||||
pic_value pic_applyk(pic_state *, struct pic_proc *, int, pic_value *);
|
||||
|
||||
pic_value pic_eval(pic_state *, pic_value, struct pic_lib *);
|
||||
|
||||
bool pic_eq_p(pic_value, pic_value);
|
||||
bool pic_eqv_p(pic_value, pic_value);
|
||||
bool pic_equal_p(pic_state *, pic_value, pic_value);
|
||||
@@ -208,6 +210,8 @@ pic_value pic_read_cstr(pic_state *, const char *);
|
||||
void pic_load(pic_state *, struct pic_port *);
|
||||
void pic_load_cstr(pic_state *, const char *);
|
||||
|
||||
pic_value pic_eval(pic_state *, pic_value, struct pic_lib *);
|
||||
|
||||
struct pic_proc *pic_make_var(pic_state *, pic_value, struct pic_proc *);
|
||||
|
||||
#define pic_deflibrary(pic, spec) \
|
||||
|
||||
@@ -35,8 +35,7 @@ struct pic_error *pic_make_error(pic_state *, pic_sym *, const char *, pic_value
|
||||
if (PIC_SETJMP(pic, cont.jmp) == 0) { \
|
||||
extern pic_value pic_native_exception_handler(pic_state *); \
|
||||
struct pic_proc *handler; \
|
||||
handler = pic_make_proc(pic, pic_native_exception_handler); \
|
||||
pic_proc_env_set(pic, handler, "cont", pic_obj_value(pic_make_cont(pic, &cont))); \
|
||||
handler = pic_lambda(pic, pic_native_exception_handler, 1, pic_obj_value(pic_make_cont(pic, &cont))); \
|
||||
do { \
|
||||
pic_push_handler(pic, handler);
|
||||
#define pic_catch_(label) \
|
||||
|
||||
@@ -26,13 +26,14 @@ struct pic_proc {
|
||||
union {
|
||||
struct {
|
||||
pic_func_t func;
|
||||
struct pic_dict *env;
|
||||
int localc;
|
||||
} f;
|
||||
struct {
|
||||
struct pic_irep *irep;
|
||||
struct pic_context *cxt;
|
||||
} i;
|
||||
} u;
|
||||
pic_value locals[1];
|
||||
};
|
||||
|
||||
#define pic_proc_func_p(proc) ((proc)->tag == PIC_PROC_TAG_FUNC)
|
||||
@@ -44,14 +45,9 @@ struct pic_proc {
|
||||
#define pic_context_p(o) (pic_type(o) == PIC_TT_CXT)
|
||||
#define pic_context_ptr(o) ((struct pic_context *)pic_ptr(o))
|
||||
|
||||
struct pic_proc *pic_make_proc(pic_state *, pic_func_t);
|
||||
struct pic_proc *pic_make_proc(pic_state *, pic_func_t, int, pic_value *);
|
||||
struct pic_proc *pic_make_proc_irep(pic_state *, struct pic_irep *, struct pic_context *);
|
||||
|
||||
struct pic_dict *pic_proc_env(pic_state *, struct pic_proc *);
|
||||
bool pic_proc_env_has(pic_state *, struct pic_proc *, const char *);
|
||||
pic_value pic_proc_env_ref(pic_state *, struct pic_proc *, const char *);
|
||||
void pic_proc_env_set(pic_state *, struct pic_proc *, const char *, pic_value);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ pic_define_standard_port(pic_state *pic, const char *name, xFILE *file, int dir)
|
||||
port->file = file;
|
||||
port->flags = dir | PIC_PORT_TEXT | PIC_PORT_OPEN;
|
||||
|
||||
pic_defvar(pic, name, pic_obj_value(port), pic_make_proc(pic, pic_assert_port));
|
||||
pic_defvar(pic, name, pic_obj_value(port), pic_make_proc(pic, pic_assert_port, 0, NULL));
|
||||
}
|
||||
|
||||
#define DEFINE_STANDARD_PORT_ACCESSOR(name, var) \
|
||||
|
||||
+65
-36
@@ -200,7 +200,7 @@ vm_push_cxt(pic_state *pic)
|
||||
{
|
||||
pic_callinfo *ci = pic->ci;
|
||||
|
||||
ci->cxt = (struct pic_context *)pic_obj_alloc(pic, sizeof(struct pic_context) + sizeof(pic_value) * ci->regc, PIC_TT_CXT);
|
||||
ci->cxt = (struct pic_context *)pic_obj_alloc(pic, offsetof(struct pic_context, storage) + sizeof(pic_value) * ci->regc, PIC_TT_CXT);
|
||||
ci->cxt->up = ci->up;
|
||||
ci->cxt->regc = ci->regc;
|
||||
ci->cxt->regs = ci->regs;
|
||||
@@ -836,6 +836,30 @@ pic_vcall(pic_state *pic, struct pic_proc *proc, int n, va_list ap)
|
||||
return pic_apply(pic, proc, n, args);
|
||||
}
|
||||
|
||||
struct pic_proc *
|
||||
pic_lambda(pic_state *pic, pic_func_t f, int n, ...)
|
||||
{
|
||||
struct pic_proc *proc;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, n);
|
||||
proc = pic_vlambda(pic, f, n, ap);
|
||||
va_end(ap);
|
||||
return proc;
|
||||
}
|
||||
|
||||
struct pic_proc *
|
||||
pic_vlambda(pic_state *pic, pic_func_t f, int n, va_list ap)
|
||||
{
|
||||
pic_value *env = pic_alloca(pic, sizeof(pic_value) * n);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
env[i] = va_arg(ap, pic_value);
|
||||
}
|
||||
return pic_make_proc(pic, f, n, env);
|
||||
}
|
||||
|
||||
void
|
||||
pic_define(pic_state *pic, struct pic_lib *lib, const char *name, pic_value val)
|
||||
{
|
||||
@@ -855,9 +879,9 @@ pic_define(pic_state *pic, struct pic_lib *lib, const char *name, pic_value val)
|
||||
}
|
||||
|
||||
void
|
||||
pic_defun(pic_state *pic, const char *name, pic_func_t cfunc)
|
||||
pic_defun(pic_state *pic, const char *name, pic_func_t f)
|
||||
{
|
||||
pic_define(pic, pic->lib, name, pic_obj_value(pic_make_proc(pic, cfunc)));
|
||||
pic_define(pic, pic->lib, name, pic_obj_value(pic_make_proc(pic, f, 0, NULL)));
|
||||
pic_export(pic, pic_intern_cstr(pic, name));
|
||||
}
|
||||
|
||||
@@ -896,6 +920,36 @@ pic_set(pic_state *pic, struct pic_lib *lib, const char *name, pic_value val)
|
||||
vm_gset(pic, uid, val);
|
||||
}
|
||||
|
||||
pic_value
|
||||
pic_closure_ref(pic_state *pic, int n)
|
||||
{
|
||||
struct pic_proc *self;
|
||||
|
||||
self = pic_proc_ptr(GET_OPERAND(pic, 0));
|
||||
|
||||
assert(pic_proc_func_p(self));
|
||||
|
||||
if (n < 0 || self->u.f.localc <= n) {
|
||||
pic_errorf(pic, "pic_closure_ref: index out of range (%d)", n);
|
||||
}
|
||||
return pic_proc_ptr(GET_OPERAND(pic, 0))->locals[n];
|
||||
}
|
||||
|
||||
void
|
||||
pic_closure_set(pic_state *pic, int n, pic_value v)
|
||||
{
|
||||
struct pic_proc *self;
|
||||
|
||||
self = pic_proc_ptr(GET_OPERAND(pic, 0));
|
||||
|
||||
assert(pic_proc_func_p(self));
|
||||
|
||||
if (n < 0 || self->u.f.localc <= n) {
|
||||
pic_errorf(pic, "pic_closure_ref: index out of range (%d)", n);
|
||||
}
|
||||
pic_proc_ptr(GET_OPERAND(pic, 0))->locals[n] = v;
|
||||
}
|
||||
|
||||
pic_value
|
||||
pic_funcall(pic_state *pic, struct pic_lib *lib, const char *name, int n, ...)
|
||||
{
|
||||
@@ -943,14 +997,18 @@ pic_irep_decref(pic_state *pic, struct pic_irep *irep)
|
||||
}
|
||||
|
||||
struct pic_proc *
|
||||
pic_make_proc(pic_state *pic, pic_func_t func)
|
||||
pic_make_proc(pic_state *pic, pic_func_t func, int n, pic_value *env)
|
||||
{
|
||||
struct pic_proc *proc;
|
||||
int i;
|
||||
|
||||
proc = (struct pic_proc *)pic_obj_alloc(pic, sizeof(struct pic_proc), PIC_TT_PROC);
|
||||
proc = (struct pic_proc *)pic_obj_alloc(pic, offsetof(struct pic_proc, locals) + sizeof(pic_value) * n, PIC_TT_PROC);
|
||||
proc->tag = PIC_PROC_TAG_FUNC;
|
||||
proc->u.f.func = func;
|
||||
proc->u.f.env = NULL;
|
||||
proc->u.f.localc = n;
|
||||
for (i = 0; i < n; ++i) {
|
||||
proc->locals[i] = env[i];
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -959,7 +1017,7 @@ pic_make_proc_irep(pic_state *pic, struct pic_irep *irep, struct pic_context *cx
|
||||
{
|
||||
struct pic_proc *proc;
|
||||
|
||||
proc = (struct pic_proc *)pic_obj_alloc(pic, sizeof(struct pic_proc), PIC_TT_PROC);
|
||||
proc = (struct pic_proc *)pic_obj_alloc(pic, offsetof(struct pic_proc, locals), PIC_TT_PROC);
|
||||
proc->tag = PIC_PROC_TAG_IREP;
|
||||
proc->u.i.irep = irep;
|
||||
proc->u.i.cxt = cxt;
|
||||
@@ -967,35 +1025,6 @@ pic_make_proc_irep(pic_state *pic, struct pic_irep *irep, struct pic_context *cx
|
||||
return proc;
|
||||
}
|
||||
|
||||
struct pic_dict *
|
||||
pic_proc_env(pic_state *pic, struct pic_proc *proc)
|
||||
{
|
||||
assert(pic_proc_func_p(proc));
|
||||
|
||||
if (! proc->u.f.env) {
|
||||
proc->u.f.env = pic_make_dict(pic);
|
||||
}
|
||||
return proc->u.f.env;
|
||||
}
|
||||
|
||||
bool
|
||||
pic_proc_env_has(pic_state *pic, struct pic_proc *proc, const char *key)
|
||||
{
|
||||
return pic_dict_has(pic, pic_proc_env(pic, proc), pic_intern_cstr(pic, key));
|
||||
}
|
||||
|
||||
pic_value
|
||||
pic_proc_env_ref(pic_state *pic, struct pic_proc *proc, const char *key)
|
||||
{
|
||||
return pic_dict_ref(pic, pic_proc_env(pic, proc), pic_intern_cstr(pic, key));
|
||||
}
|
||||
|
||||
void
|
||||
pic_proc_env_set(pic_state *pic, struct pic_proc *proc, const char *key, pic_value val)
|
||||
{
|
||||
pic_dict_set(pic, pic_proc_env(pic, proc), pic_intern_cstr(pic, key), val);
|
||||
}
|
||||
|
||||
static pic_value
|
||||
pic_proc_proc_p(pic_state *pic)
|
||||
{
|
||||
|
||||
+10
-13
@@ -4,15 +4,6 @@
|
||||
|
||||
#include "picrin.h"
|
||||
|
||||
static pic_value
|
||||
var_conv(pic_state *pic, struct pic_proc *var, pic_value val)
|
||||
{
|
||||
if (pic_proc_env_has(pic, var, "conv") != 0) {
|
||||
return pic_call(pic, pic_proc_ptr(pic_proc_env_ref(pic, var, "conv")), 1, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static pic_value
|
||||
var_get(pic_state *pic, struct pic_proc *var)
|
||||
{
|
||||
@@ -52,7 +43,13 @@ var_call(pic_state *pic)
|
||||
if (n == 0) {
|
||||
return var_get(pic, self);
|
||||
} else {
|
||||
return var_set(pic, self, var_conv(pic, self, val));
|
||||
pic_value conv;
|
||||
|
||||
conv = pic_closure_ref(pic, 0);
|
||||
if (! pic_false_p(conv)) {
|
||||
val = pic_call(pic, pic_proc_ptr(conv), 1, val);
|
||||
}
|
||||
return var_set(pic, self, val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +57,12 @@ struct pic_proc *
|
||||
pic_make_var(pic_state *pic, pic_value init, struct pic_proc *conv)
|
||||
{
|
||||
struct pic_proc *var;
|
||||
|
||||
var = pic_make_proc(pic, var_call);
|
||||
pic_value c = pic_false_value();
|
||||
|
||||
if (conv != NULL) {
|
||||
pic_proc_env_set(pic, var, "conv", pic_obj_value(conv));
|
||||
c = pic_obj_value(conv);
|
||||
}
|
||||
var = pic_lambda(pic, var_call, 1, c);
|
||||
|
||||
pic_call(pic, var, 1, init);
|
||||
|
||||
|
||||
+2
-7
@@ -115,7 +115,7 @@ weak_call(pic_state *pic)
|
||||
pic_errorf(pic, "attempted to set a non-object key '~s' in an ephemeron", key);
|
||||
}
|
||||
|
||||
weak = pic_weak_ptr(pic_proc_env_ref(pic, self, "weak"));
|
||||
weak = pic_weak_ptr(pic_closure_ref(pic, 0));
|
||||
|
||||
if (n == 1) {
|
||||
return weak_get(pic, weak, pic_obj_ptr(key));
|
||||
@@ -127,16 +127,11 @@ weak_call(pic_state *pic)
|
||||
static pic_value
|
||||
pic_weak_make_ephemeron(pic_state *pic)
|
||||
{
|
||||
struct pic_weak *weak;
|
||||
struct pic_proc *proc;
|
||||
|
||||
pic_get_args(pic, "");
|
||||
|
||||
weak = pic_make_weak(pic);
|
||||
|
||||
proc = pic_make_proc(pic, weak_call);
|
||||
|
||||
pic_proc_env_set(pic, proc, "weak", pic_obj_value(weak));
|
||||
proc = pic_lambda(pic, weak_call, 1, pic_obj_value(pic_make_weak(pic)));
|
||||
|
||||
return pic_obj_value(proc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user