diff --git a/extlib/benz/codegen.c b/extlib/benz/codegen.c index a14a2886..d4f2c187 100644 --- a/extlib/benz/codegen.c +++ b/extlib/benz/codegen.c @@ -436,7 +436,7 @@ define_var(pic_state *pic, analyze_scope *scope, pic_sym *sym) int ret; if (search_scope(scope, sym)) { - if (scope->depth > 0 || (pic_dict_has(pic, pic->globals, sym) && ! pic_invalid_p(pic_cdr(pic, pic_dict_ref(pic, pic->globals, sym))))) { + if (scope->depth > 0 || (pic_dict_has(pic, pic->globals, sym) && ! pic_invalid_p(pic_box_ptr(pic_dict_ref(pic, pic->globals, sym))->value))) { pic_warnf(pic, "redefining variable: ~s", pic_obj_value(sym)); } return; @@ -782,15 +782,15 @@ index_local(codegen_context *cxt, pic_sym *sym) static int index_global(pic_state *pic, codegen_context *cxt, pic_sym *name) { - extern pic_value pic_vm_gref_slot(pic_state *, pic_sym *); + extern struct pic_box *pic_vm_gref_slot(pic_state *, pic_sym *); int pidx; - pic_value slot; + struct pic_box *slot; slot = pic_vm_gref_slot(pic, name); check_pool_size(pic, cxt); pidx = (int)cxt->plen++; - cxt->pool[pidx] = slot; + cxt->pool[pidx] = pic_obj_value(slot); return pidx; } diff --git a/extlib/benz/gc.c b/extlib/benz/gc.c index 2e7ae20f..a7096cca 100644 --- a/extlib/benz/gc.c +++ b/extlib/benz/gc.c @@ -35,6 +35,7 @@ union object { struct pic_port port; struct pic_error err; struct pic_lib lib; + struct pic_box box; struct pic_checkpoint cp; }; @@ -405,6 +406,12 @@ gc_mark_object(pic_state *pic, union object *obj) pic->heap->regs = reg; break; } + case PIC_TT_BOX: { + if (pic_obj_p(obj->box.value)) { + LOOP(pic_obj_ptr(obj->box.value)); + } + break; + } case PIC_TT_CP: { if (obj->cp.prev) { gc_mark_object(pic, (union object *)obj->cp.prev); @@ -597,6 +604,7 @@ gc_finalize_object(pic_state *pic, union object *obj) case PIC_TT_LIB: case PIC_TT_RECORD: case PIC_TT_CP: + case PIC_TT_BOX: break; case PIC_TT_NIL: diff --git a/extlib/benz/include/picrin.h b/extlib/benz/include/picrin.h index 30ec8a58..50737ea3 100644 --- a/extlib/benz/include/picrin.h +++ b/extlib/benz/include/picrin.h @@ -102,14 +102,15 @@ struct pic_state { pic_sym *uDEFINE, *uLAMBDA, *uIF, *uBEGIN, *uQUOTE, *uSETBANG, *uDEFINE_MACRO; pic_sym *uDEFINE_LIBRARY, *uIMPORT, *uEXPORT, *uCOND_EXPAND; + pic_sym *uCONS, *uCAR, *uCDR, *uNILP, *uSYMBOLP, *uPAIRP; pic_sym *uADD, *uSUB, *uMUL, *uDIV, *uEQ, *uLT, *uLE, *uGT, *uGE, *uNOT; pic_value pCONS, pCAR, pCDR, pNILP, pPAIRP, pSYMBOLP, pNOT; pic_value pADD, pSUB, pMUL, pDIV, pEQ, pLT, pLE, pGT, pGE; - pic_value cCONS, cCAR, cCDR, cNILP, cPAIRP, cSYMBOLP, cNOT; - pic_value cADD, cSUB, cMUL, cDIV, cEQ, cLT, cLE, cGT, cGE; + struct pic_box *cCONS, *cCAR, *cCDR, *cNILP, *cPAIRP, *cSYMBOLP, *cNOT; + struct pic_box *cADD, *cSUB, *cMUL, *cDIV, *cEQ, *cLT, *cLE, *cGT, *cGE; struct pic_lib *PICRIN_BASE; struct pic_lib *PICRIN_USER; @@ -268,6 +269,7 @@ pic_value pic_fdisplay(pic_state *, pic_value, xFILE *); #include "picrin/symbol.h" #include "picrin/vector.h" #include "picrin/reg.h" +#include "picrin/box.h" #if defined(__cplusplus) } diff --git a/extlib/benz/include/picrin/box.h b/extlib/benz/include/picrin/box.h new file mode 100644 index 00000000..dcfa676a --- /dev/null +++ b/extlib/benz/include/picrin/box.h @@ -0,0 +1,34 @@ +/** + * See Copyright Notice in picrin.h + */ + +#ifndef PICRIN_BOX_H +#define PICRIN_BOX_H + +#if defined(__cplusplus) +extern "C" { +#endif + +struct pic_box { + PIC_OBJECT_HEADER + pic_value value; +}; + +#define pic_box_p(v) (pic_type(v) == PIC_TT_BOX) +#define pic_box_ptr(v) ((struct pic_box *)pic_ptr(v)) + +PIC_INLINE struct pic_box * +pic_box(pic_state *pic, pic_value value) +{ + struct pic_box *box; + + box = (struct pic_box *)pic_obj_alloc(pic, sizeof(struct pic_box), PIC_TT_BOX); + box->value = value; + return box; +} + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/extlib/benz/include/picrin/type.h b/extlib/benz/include/picrin/type.h index 0df475a8..4de8d279 100644 --- a/extlib/benz/include/picrin/type.h +++ b/extlib/benz/include/picrin/type.h @@ -156,6 +156,7 @@ enum pic_tt { PIC_TT_DICT, PIC_TT_REG, PIC_TT_RECORD, + PIC_TT_BOX, PIC_TT_CXT, PIC_TT_IREP, PIC_TT_CP @@ -313,6 +314,8 @@ pic_type_repr(enum pic_tt tt) return "dict"; case PIC_TT_REG: return "reg"; + case PIC_TT_BOX: + return "box"; case PIC_TT_RECORD: return "record"; case PIC_TT_CP: diff --git a/extlib/benz/state.c b/extlib/benz/state.c index 99127266..86f3d88a 100644 --- a/extlib/benz/state.c +++ b/extlib/benz/state.c @@ -127,7 +127,7 @@ static void pic_init_core(pic_state *pic) { void pic_define_syntactic_keyword_(pic_state *, struct pic_env *, pic_sym *, pic_sym *); - pic_value pic_vm_gref_slot(pic_state *, pic_sym *); + struct pic_box *pic_vm_gref_slot(pic_state *, pic_sym *); pic_init_features(pic); @@ -434,22 +434,22 @@ pic_open(pic_allocf allocf, void *userdata) /* turn on GC */ pic->gc_enable = true; - pic->cCONS = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cCAR = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cCDR = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cNILP = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cSYMBOLP = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cPAIRP = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cNOT = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cADD = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cSUB = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cMUL = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cDIV = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cEQ = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cLT = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cLE = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cGT = pic_cons(pic, pic_false_value(), pic_invalid_value()); - pic->cGE = pic_cons(pic, pic_false_value(), pic_invalid_value()); + pic->cCONS = pic_box(pic, pic_invalid_value()); + pic->cCAR = pic_box(pic, pic_invalid_value()); + pic->cCDR = pic_box(pic, pic_invalid_value()); + pic->cNILP = pic_box(pic, pic_invalid_value()); + pic->cSYMBOLP = pic_box(pic, pic_invalid_value()); + pic->cPAIRP = pic_box(pic, pic_invalid_value()); + pic->cNOT = pic_box(pic, pic_invalid_value()); + pic->cADD = pic_box(pic, pic_invalid_value()); + pic->cSUB = pic_box(pic, pic_invalid_value()); + pic->cMUL = pic_box(pic, pic_invalid_value()); + pic->cDIV = pic_box(pic, pic_invalid_value()); + pic->cEQ = pic_box(pic, pic_invalid_value()); + pic->cLT = pic_box(pic, pic_invalid_value()); + pic->cLE = pic_box(pic, pic_invalid_value()); + pic->cGT = pic_box(pic, pic_invalid_value()); + pic->cGE = pic_box(pic, pic_invalid_value()); pic_init_core(pic); diff --git a/extlib/benz/vm.c b/extlib/benz/vm.c index d586832b..2f291111 100644 --- a/extlib/benz/vm.c +++ b/extlib/benz/vm.c @@ -386,32 +386,35 @@ pic_get_args(pic_state *pic, const char *format, ...) return argc; } -pic_value +struct pic_box * pic_vm_gref_slot(pic_state *pic, pic_sym *uid) { - pic_value slot; + struct pic_box *box; if (pic_dict_has(pic, pic->globals, uid)) { - return pic_dict_ref(pic, pic->globals, uid); + return pic_box_ptr(pic_dict_ref(pic, pic->globals, uid)); } - slot = pic_cons(pic, pic_obj_value(uid), pic_invalid_value()); - pic_dict_set(pic, pic->globals, uid, slot); - return slot; + box = pic_box(pic, pic_invalid_value()); + pic_dict_set(pic, pic->globals, uid, pic_obj_value(box)); + return box; } static pic_value -vm_gref(pic_state *pic, pic_value slot) +vm_gref(pic_state *pic, struct pic_box *slot, pic_sym *uid) { - if (pic_invalid_p(pic_cdr(pic, slot))) { - pic_errorf(pic, "uninitialized global variable: ~a", pic_car(pic, slot)); + if (pic_invalid_p(slot->value)) { + if (uid == NULL) { + uid = pic_intern(pic, "unknown"); /* FIXME */ + } + pic_errorf(pic, "uninitialized global variable: ~a", uid); } - return pic_cdr(pic, slot); + return slot->value; } static void -vm_gset(pic_state *pic, pic_value slot, pic_value value) +vm_gset(struct pic_box *slot, pic_value value) { - pic_set_cdr(pic, slot, value); + slot->value = value; } static void @@ -630,11 +633,11 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args) NEXT; } CASE(OP_GREF) { - PUSH(vm_gref(pic, pic->ci->irep->pool[c.u.i])); + PUSH(vm_gref(pic, pic_box_ptr(pic->ci->irep->pool[c.u.i]), NULL)); /* FIXME */ NEXT; } CASE(OP_GSET) { - vm_gset(pic, pic->ci->irep->pool[c.u.i], POP()); + vm_gset(pic_box_ptr(pic->ci->irep->pool[c.u.i]), POP()); PUSH(pic_undef_value()); NEXT; } @@ -847,7 +850,7 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args) } #define check_condition(name, n) do { \ - if (! pic_eq_p(pic->p##name, pic_cdr(pic, pic->c##name))) \ + if (! pic_eq_p(pic->p##name, pic->c##name->value)) \ goto L_CALL; \ if (c.u.i != n + 1) \ goto L_CALL; \ @@ -1161,7 +1164,7 @@ pic_ref(pic_state *pic, struct pic_lib *lib, const char *name) pic_errorf(pic, "symbol \"%s\" not defined in library ~s", name, lib->name); } - return vm_gref(pic, pic_vm_gref_slot(pic, uid)); + return vm_gref(pic, pic_vm_gref_slot(pic, uid), uid); } void @@ -1175,7 +1178,7 @@ pic_set(pic_state *pic, struct pic_lib *lib, const char *name, pic_value val) pic_errorf(pic, "symbol \"%s\" not defined in library ~s", name, lib->name); } - vm_gset(pic, pic_vm_gref_slot(pic, uid), val); + vm_gset(pic_vm_gref_slot(pic, uid), val); } pic_value