diff --git a/include/picrin/irep.h b/include/picrin/irep.h index 8e032d5d..7cdbc41d 100644 --- a/include/picrin/irep.h +++ b/include/picrin/irep.h @@ -11,6 +11,7 @@ enum pic_opcode { OP_GREF, OP_GSET, OP_LREF, + OP_CREF, OP_JMP, OP_JMPIF, OP_CALL, @@ -32,6 +33,10 @@ struct pic_code { union { double f; int i; + struct { + short depth; + short idx; + } c; } u; }; diff --git a/src/codegen.c b/src/codegen.c index e7a7bdf1..df335f10 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -506,6 +506,9 @@ print_irep(pic_state *pic, struct pic_irep *irep) case OP_LREF: printf("OP_LREF\t%d\n", irep->code[i].u.i); break; + case OP_CREF: + printf("OP_CREF\t%d\t%d\n", irep->code[i].u.c.depth, irep->code[i].u.c.idx); + break; case OP_JMP: printf("OP_JMP\t%d\n", irep->code[i].u.i); break; diff --git a/src/vm.c b/src/vm.c index 946eaf04..0847794f 100644 --- a/src/vm.c +++ b/src/vm.c @@ -118,9 +118,10 @@ pic_run(pic_state *pic, struct pic_proc *proc, pic_value args) #if PIC_DIRECT_THREADED_VM static void *oplabels[] = { &&L_OP_POP, &&L_OP_PUSHNIL, &&L_OP_PUSHTRUE, &&L_OP_PUSHFALSE, &&L_OP_PUSHNUM, - &&L_OP_PUSHCONST, &&L_OP_GREF, &&L_OP_GSET, &&L_OP_LREF, &&L_OP_JMP, &&L_OP_JMPIF, - &&L_OP_CALL, &&L_OP_RET, &&L_OP_LAMBDA, &&L_OP_CONS, &&L_OP_CAR, &&L_OP_CDR, - &&L_OP_NILP, &&L_OP_ADD, &&L_OP_SUB, &&L_OP_MUL, &&L_OP_DIV, &&L_OP_STOP + &&L_OP_PUSHCONST, &&L_OP_GREF, &&L_OP_GSET, &&L_OP_LREF, &&L_OP_CREF, + &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_CALL, &&L_OP_RET, &&L_OP_LAMBDA, &&L_OP_CONS, + &&L_OP_CAR, &&L_OP_CDR, &&L_OP_NILP, &&L_OP_ADD, &&L_OP_SUB, &&L_OP_MUL, + &&L_OP_DIV, &&L_OP_STOP }; #endif @@ -177,6 +178,17 @@ pic_run(pic_state *pic, struct pic_proc *proc, pic_value args) PUSH(pic->ci->fp[pc->u.i]); NEXT; } + CASE(OP_CREF) { + int depth = pc->u.c.depth; + struct pic_env *env; + + env = pic_proc_ptr(*pic->ci->fp)->env; + while (depth--) { + env = env->up; + } + PUSH(env->values[pc->u.c.idx]); + NEXT; + } CASE(OP_JMP) { pc += pc->u.i; JUMP;