コード例 #1
0
static void leaveblock(FuncState *fs)
{
    BlockCnt *bl = fs->bl;
    LexState *ls = fs->ls;

    if (bl->previous && bl->upval)
    {
        /* create a 'jump to here' to close upvalues */
        int j = luaK_jump(fs);
        luaK_patchclose(fs, j, bl->nactvar);
        luaK_patchtohere(fs, j);
    }

    if (bl->isloop)
        breaklabel(ls); /* close pending breaks */

    fs->bl = bl->previous;
    removevars(fs, bl->nactvar);
    lua_assert(bl->nactvar == fs->nactvar);
    fs->freereg      = fs->nactvar; /* free registers */
    ls->dyd->label.n = bl->firstlabel; /* remove local labels */
    if (bl->previous) /* inner block? */
        movegotosout(fs, bl); /* update pending gotos to outer block */
    else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */
        undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */
}
コード例 #2
0
ファイル: lparser.c プロジェクト: bcrist/lua
/*
** export pending gotos to outer level, to check them against
** outer labels; if the block being exited has upvalues, and
** the goto exits the scope of any variable (which can be the
** upvalue), close those variables being exited.
*/
static void movegotosout (FuncState *fs, BlockCnt *bl) {
  int i = bl->firstgoto;
  Labellist *gl = &fs->ls->dyd->gt;
  /* correct pending gotos to current block and try to close it
     with visible labels */
  while (i < gl->n) {
    Labeldesc *gt = &gl->arr[i];
    if (gt->nactvar > bl->nactvar) {
      if (bl->upval)
        luaK_patchclose(fs, gt->pc, bl->nactvar);
      gt->nactvar = bl->nactvar;
    }
    if (!findlabel(fs->ls, i))
      i++;  /* move to next one */
  }
}
コード例 #3
0
ファイル: lparser.c プロジェクト: bcrist/lua
/*
** try to close a goto with existing labels; this solves backward jumps
*/
static int findlabel (LexState *ls, int g) {
  int i;
  BlockCnt *bl = ls->fs->bl;
  Dyndata *dyd = ls->dyd;
  Labeldesc *gt = &dyd->gt.arr[g];
  /* check labels in current block for a match */
  for (i = bl->firstlabel; i < dyd->label.n; i++) {
    Labeldesc *lb = &dyd->label.arr[i];
    if (eqstr(lb->name, gt->name)) {  /* correct label? */
      if (gt->nactvar > lb->nactvar &&
          (bl->upval || dyd->label.n > bl->firstlabel))
        luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
      closegoto(ls, g, lb);  /* close it */
      return 1;
    }
  }
  return 0;  /* label not found; cannot close goto */
}
コード例 #4
0
ファイル: lparser.cpp プロジェクト: swizl/lua
/*static*/ void FuncState::leaveblock (/*FuncState *fs*/) {
	//BlockCnt *bl = fs->bl;
	//LexState *ls = fs->ls;
	if (bl->previous && bl->upval) {
		/* create a 'jump to here' to close upvalues */
		int j = luaK_jump();
		luaK_patchclose(j, bl->nactvar);
		luaK_patchtohere(j);
	}
	if (bl->isloop)
		ls->breaklabel();  /* close pending breaks */
	bl = bl->previous;
	removevars(bl->nactvar);
	lua_assert(bl->nactvar == nactvar);
	free_reg = nactvar;  /* free registers */
	ls->dyd->label.n = bl->firstlabel;  /* remove local labels */
	if (bl->previous)  /* inner block? */
		movegotosout(bl);  /* update pending gotos to outer block */
	else if (bl->firstgoto < ls->dyd->gt.n)  /* pending gotos in outer block? */
		ls->undefgoto(&ls->dyd->gt.arr[bl->firstgoto]);  /* error */
}