scmno****@osdn*****
scmno****@osdn*****
Sat Jun 30 05:11:06 JST 2018
changeset c27307dc1b06 in quipu/quipu details: http://hg.osdn.jp/view/quipu/quipu?cmd=changeset;node=c27307dc1b06 user: Agustina Arzille <avarz****@riseu*****> date: Fri Jun 29 17:10:49 2018 -0300 description: Correct captured variables in 'let' forms diffstat: bytecode.cpp | 137 ++++++++++++++++++++++++++++----------------------------- bytecode.h | 1 - compiler.cpp | 33 ++----------- eval.cpp | 100 ++++++++++++++++++++++++++--------------- utils/opnames | 1 - 5 files changed, 137 insertions(+), 135 deletions(-) diffs (truncated from 417 to 300 lines): diff -r 411c30c09598 -r c27307dc1b06 bytecode.cpp --- a/bytecode.cpp Wed Jun 27 17:25:37 2018 -0300 +++ b/bytecode.cpp Fri Jun 29 17:10:49 2018 -0300 @@ -17,10 +17,10 @@ static const char OPC_NAMES[] = "nop\0dup\0pop\0ret\0is\0not\0cons\0list\0car\0cdr\0cadr\0nputcar\0" "nputcdr\0apply\0tapply\0loadt\0loadnil\0load0\0load1\0loadi8\0loada0\0" - "loada1\0loadc00\0loadc01\0loadap0\0loadap1\0mkcont\0captenv\0closure\0" - "tryend\0raise\0raise2\0ldcaller\0prepfrm\0argc\0argc.l\0vargc\0vargc.l\0" - "jmp\0jmp.l\0brt\0brt.l\0brn\0brn.l\0brneq\0brneq.l\0tcall\0tcall.l\0" - "call\0call.l\0setc\0setc.l\0seta\0seta.l\0setap\0setap.l\0setg\0setg.l\0" + "loada1\0loadc00\0loadc01\0loadap0\0loadap1\0mkcont\0closure\0tryend\0" + "raise\0raise2\0ldcaller\0skipfrm\0argc\0argc.l\0vargc\0vargc.l\0jmp\0" + "jmp.l\0brt\0brt.l\0brn\0brn.l\0brneq\0brneq.l\0tcall\0tcall.l\0call\0" + "call.l\0setc\0setc.l\0seta\0seta.l\0setap\0setap.l\0setg\0setg.l\0" "loadc\0loadc.l\0loada\0loada.l\0loadap\0loadap.l\0loadg\0loadg.l\0" "loadv\0loadv.l\0loadx\0loadx.l\0bind\0bind.l\0recur\0recur.l\0trecur\0" "trecur.l\0mkframe\0mkframe.l\0unwind\0unwind.l\0trybegin\0trybegin.l\0" @@ -66,71 +66,70 @@ { 138, 1 | BC_LOAD_FORM | BC_PURE_FORM }, // loadap0 { 146, 1 | BC_LOAD_FORM | BC_PURE_FORM }, // loadap1 { 154, 1 | BC_LOAD_FORM }, // mkcont - { 161, 0 }, // captenv - { 169, 0 }, // closure - { 177, 0 }, // tryend - { 184, 0 }, // raise - { 190, 0 }, // raise2 - { 197, 0 }, // ldcaller - { 206, 0 }, // prepfrm - { 214, 1 }, // argc - { 219, 1 | BC_LONG_FORM }, // argc.l - { 226, 1 }, // vargc - { 232, 1 | BC_LONG_FORM }, // vargc.l - { 240, 1 | BC_BRANCH_FORM }, // jmp - { 244, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // jmp.l - { 250, 1 | BC_BRANCH_FORM }, // brt - { 254, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // brt.l - { 260, 1 | BC_BRANCH_FORM }, // brn - { 264, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // brn.l - { 270, 1 | BC_BRANCH_FORM }, // brneq - { 276, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // brneq.l - { 284, 1 | BC_CALL_FORM }, // tcall - { 290, 1 | BC_CALL_FORM | BC_LONG_FORM }, // tcall.l - { 298, 1 | BC_CALL_FORM }, // call - { 303, 1 | BC_CALL_FORM | BC_LONG_FORM }, // call.l - { 310, 2 }, // setc - { 315, 2 | BC_LONG_FORM }, // setc.l - { 322, 1 }, // seta - { 327, 1 | BC_LONG_FORM }, // seta.l - { 334, 2 }, // setap - { 340, 2 | BC_LONG_FORM }, // setap.l - { 348, 1 }, // setg - { 353, 1 | BC_LONG_FORM }, // setg.l - { 360, 2 | BC_LOAD_FORM | BC_PURE_FORM }, // loadc - { 366, 2 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loadc.l - { 374, 1 | BC_LOAD_FORM | BC_PURE_FORM }, // loada - { 380, 1 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loada.l - { 388, 2 | BC_LOAD_FORM | BC_PURE_FORM }, // loadap - { 395, 2 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loadap.l - { 404, 1 | BC_LOAD_FORM }, // loadg - { 410, 1 | BC_LOAD_FORM | BC_LONG_FORM }, // loadg.l - { 418, 1 | BC_LOAD_FORM | BC_PURE_FORM }, // loadv - { 424, 1 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loadv.l - { 432, 1 | BC_LOAD_FORM }, // loadx - { 438, 1 | BC_LOAD_FORM | BC_LONG_FORM }, // loadx.l - { 446, 1 }, // bind - { 451, 1 | BC_LONG_FORM }, // bind.l - { 458, 1 | BC_CALL_FORM }, // recur - { 464, 1 | BC_CALL_FORM | BC_LONG_FORM }, // recur.l - { 472, 1 | BC_CALL_FORM }, // trecur - { 479, 1 | BC_CALL_FORM | BC_LONG_FORM }, // trecur.l - { 488, 1 }, // mkframe - { 496, 1 | BC_LONG_FORM }, // mkframe.l - { 506, 1 }, // unwind - { 513, 1 | BC_LONG_FORM }, // unwind.l - { 522, 1 | BC_BRANCH_FORM }, // trybegin - { 531, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // trybegin.l - { 542, 1 }, // setapop - { 550, 1 | BC_LONG_FORM }, // setapop.l - { 560, 1 | BC_BRANCH_FORM }, // irtjmp - { 567, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // irtjmp.l - { 576, 2 }, // optargs - { 584, 2 | BC_LONG_FORM }, // optargs.l - { 594, 1 }, // brbound - { 602, 1 | BC_LONG_FORM }, // brbound.l - { 612, 3 }, // kwargs - { 619, 3 | BC_LONG_FORM }, // kwargs.l + { 161, 0 }, // closure + { 169, 0 }, // tryend + { 176, 0 }, // raise + { 182, 0 }, // raise2 + { 189, 0 }, // ldcaller + { 198, 0 }, // skipfrm + { 206, 1 }, // argc + { 211, 1 | BC_LONG_FORM }, // argc.l + { 218, 1 }, // vargc + { 224, 1 | BC_LONG_FORM }, // vargc.l + { 232, 1 | BC_BRANCH_FORM }, // jmp + { 236, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // jmp.l + { 242, 1 | BC_BRANCH_FORM }, // brt + { 246, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // brt.l + { 252, 1 | BC_BRANCH_FORM }, // brn + { 256, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // brn.l + { 262, 1 | BC_BRANCH_FORM }, // brneq + { 268, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // brneq.l + { 276, 1 | BC_CALL_FORM }, // tcall + { 282, 1 | BC_CALL_FORM | BC_LONG_FORM }, // tcall.l + { 290, 1 | BC_CALL_FORM }, // call + { 295, 1 | BC_CALL_FORM | BC_LONG_FORM }, // call.l + { 302, 2 }, // setc + { 307, 2 | BC_LONG_FORM }, // setc.l + { 314, 1 }, // seta + { 319, 1 | BC_LONG_FORM }, // seta.l + { 326, 2 }, // setap + { 332, 2 | BC_LONG_FORM }, // setap.l + { 340, 1 }, // setg + { 345, 1 | BC_LONG_FORM }, // setg.l + { 352, 2 | BC_LOAD_FORM | BC_PURE_FORM }, // loadc + { 358, 2 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loadc.l + { 366, 1 | BC_LOAD_FORM | BC_PURE_FORM }, // loada + { 372, 1 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loada.l + { 380, 2 | BC_LOAD_FORM | BC_PURE_FORM }, // loadap + { 387, 2 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loadap.l + { 396, 1 | BC_LOAD_FORM }, // loadg + { 402, 1 | BC_LOAD_FORM | BC_LONG_FORM }, // loadg.l + { 410, 1 | BC_LOAD_FORM | BC_PURE_FORM }, // loadv + { 416, 1 | BC_LOAD_FORM | BC_PURE_FORM | BC_LONG_FORM }, // loadv.l + { 424, 1 | BC_LOAD_FORM }, // loadx + { 430, 1 | BC_LOAD_FORM | BC_LONG_FORM }, // loadx.l + { 438, 1 }, // bind + { 443, 1 | BC_LONG_FORM }, // bind.l + { 450, 1 | BC_CALL_FORM }, // recur + { 456, 1 | BC_CALL_FORM | BC_LONG_FORM }, // recur.l + { 464, 1 | BC_CALL_FORM }, // trecur + { 471, 1 | BC_CALL_FORM | BC_LONG_FORM }, // trecur.l + { 480, 1 }, // mkframe + { 488, 1 | BC_LONG_FORM }, // mkframe.l + { 498, 1 }, // unwind + { 505, 1 | BC_LONG_FORM }, // unwind.l + { 514, 1 | BC_BRANCH_FORM }, // trybegin + { 523, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // trybegin.l + { 534, 1 }, // setapop + { 542, 1 | BC_LONG_FORM }, // setapop.l + { 552, 1 | BC_BRANCH_FORM }, // irtjmp + { 559, 1 | BC_BRANCH_FORM | BC_LONG_FORM }, // irtjmp.l + { 568, 2 }, // optargs + { 576, 2 | BC_LONG_FORM }, // optargs.l + { 586, 1 }, // brbound + { 594, 1 | BC_LONG_FORM }, // brbound.l + { 604, 3 }, // kwargs + { 611, 3 | BC_LONG_FORM }, // kwargs.l { 0, 0 } }; diff -r 411c30c09598 -r c27307dc1b06 bytecode.h --- a/bytecode.h Wed Jun 27 17:25:37 2018 -0300 +++ b/bytecode.h Fri Jun 29 17:10:49 2018 -0300 @@ -34,7 +34,6 @@ OP_LOADAP0, OP_LOADAP1, OP_MKCONT, - OP_CAPTENV, OP_CLOSURE, OP_TRYEND, OP_RAISE, diff -r 411c30c09598 -r c27307dc1b06 compiler.cpp --- a/compiler.cpp Wed Jun 27 17:25:37 2018 -0300 +++ b/compiler.cpp Fri Jun 29 17:10:49 2018 -0300 @@ -14,9 +14,6 @@ // Special instruction used to refer to labels in the code. static const int OP_LABEL = 0x100; -// Placeholder for variable captures. -static const int OP_FAKECAPT = 0x101; - #define OPX_(opc) (EXTRA_BIT | (intobj ((int)OP_##opc))) /* Opcodes that follow OP_ARGC are defined as pairs, the second one being @@ -73,8 +70,7 @@ { flg_outer_ref = 0x01, flg_captured = 0x02, - flg_emitted_captenv = 0x04, - flg_toplevel = 0x08 + flg_toplevel = 0x04 }; class frame_data @@ -643,12 +639,6 @@ lbl_loc.add (cv[it++], this->bc_len); continue; } - else if (vi == OPX_(FAKECAPT)) - { - if (this->rflags & flg_captured) - this->bytecode_write ((uint8_t)OP_CAPTENV); - continue; - } const bcode_instr *instrp = bcode_get (as_int (vi)); if (large && !instrp->long_p () && instrp->branch_p ()) @@ -950,7 +940,7 @@ { auto& f = this->frames[this->frames.size () - depth - 1]; if (this->rflags & flg_captured) - this->emit (ixs[3], intobj (f.acc + f.nargs), intobj (loc)); + this->emit (ixs[3], intobj (f.acc), intobj (loc)); else this->emit (ixs[0], intobj (f.acc + loc)); } @@ -1946,16 +1936,9 @@ * rather than a lexical or dynamic binding. */ continue; else if (first) - { /* A 'let' form must be preceeded by a stack frame, and (optionally) - * an environment capture in case the body refers to a variable - * from the outer frame. Here we emit a few placeholders that we'll - * eventually patch or remove. */ - if (!(bc.rflags & bc_emitter::flg_emitted_captenv)) - { - bc.code.push_back (OPX_(FAKECAPT)); - bc.rflags |= bc_emitter::flg_emitted_captenv; - } - + { /* Prepend the stack frame construction opcode when we are + * in 'captured' mode. Note that this will implicitly capture + * all the lexical variables in all the parent frames. */ bc.emit (OPX_(MKFRAME), intobj (nargs)); ++bc.cur_f().stkdisp; bc.push_f (); @@ -1978,12 +1961,9 @@ bc.emit (OPX_(BIND), xcar (bindings)); continue; } - else if (!(bc.rflags & bc_emitter::flg_captured)) - bc.emit (OPX_(SETAPOP), intobj (nlex + bc.cur_f().acc)); else { - bc.emit (OPX_(SETAP), - intobj (bc.cur_f().acc + nargs), intobj (nlex)); + bc.emit (OPX_(SETAP), intobj (bc.cur_f().acc), intobj (nlex)); bc.emit (OPX_(POP)); } @@ -2039,7 +2019,6 @@ --bc.cur_f().stkdisp; bc.code.resize (psize); syms->car = ctvs->car = NIL; - bc.rflags &= ~bc_emitter::flg_captured; nlex = nctv = 0; return (false); } diff -r 411c30c09598 -r c27307dc1b06 eval.cpp --- a/eval.cpp Wed Jun 27 17:25:37 2018 -0300 +++ b/eval.cpp Fri Jun 29 17:10:49 2018 -0300 @@ -203,6 +203,41 @@ return (ret); } +static object +captenv (interpreter *interp, uint32_t lastf) +{ + uint32_t cf = interp->cur_frame; + object *lp = nullptr; + object *retp = &interp->stack[cf - interpreter::frame_size - + as_int (interp->stack[cf - 3])]; + + do + { + int sx = as_int (interp->stack[cf - 3]); + if (interp->dynframe_captured (cf - 1)) + break; + else if (sx == 0) + { + cf = as_int (interp->stack[cf - 4]); + continue; + } + + array *ap = as_array (alloc_array (interp, sx + 1, NIL)); + int nbp = cf - interpreter::frame_size - sx; + copy_objs (ap->data, &interp->stack[nbp], sx + 1); + interp->stack[nbp] = interp->alval; + if (lp != nullptr) + *lp = interp->alval; + + lp = &ap->data[sx]; + interp->dynframe_set_captured (cf - 1); + cf = as_int (interp->stack[cf - 4]); + } + while (cf > lastf); + + return (*retp); +} + // Additional data used in function calls. class call_data { @@ -220,7 +255,7 @@ int32_t sx = 0; const uint8_t *ip;