[Quipu-dev] quipu/quipu: Correct captured variables in 'let' forms

Back to archive index

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;




More information about the Quipu-dev mailing list
Back to archive index