lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Dear Lua users,

I am currently trying to understand how the Lua interpreter (lparser.c) parses
if statements.

I am trying to add an extension to the if .. then .. elseif .. end statement
that will always be executed if at least one of the if/elseif conditions evaluates
to true - to save some code if every `then` clause contains equal statements.

Would you please explain how the luaK_concat and luaK_patchtohere functions
work and what targets are stored to the flist and escapelist jump variables ?
Do you know how to implement such a feature or give me some hints ?

All my experiments to implement such a feature failed despite code analysis
of the lcode.c functions (which I often do not understand).

Thank you,



The extended if structure would look something like this:

Old                      New

if cond1 then            if cond1 then
    statement1              statement1
elseif cond2             elseif cond 2 then
    statement2              statement2
                         finally  -- will always be executed of one cond is true
else                     else
    other statements        other statements
end;                     end;

Of course, statementsXY could be put into a procedure to be called from within the
if statement. Also situations in which a `finally` clause would be helpful are quite rare.

static void ifstat (LexState *ls, int line) {
  /* ifstat -> IF cond THEN block {ELIF cond THEN block} [ELSE block] FI */
  FuncState *fs = ls->fs;
  int flist;
  int escapelist = NO_JUMP;
  flist = test_then_block(ls);  /* IF cond THEN block */
  while (ls->t.token == TK_ELSEIF) {  /* changed Oct. 12, 2006, changed 0.4.0 */
    luaK_concat(fs, &escapelist, luaK_jump(fs));
    luaK_patchtohere(fs, flist);
    flist = test_then_block(ls);  /* ELIF cond THEN block */
  if (ls->t.token == TK_FINALLY) {  /* does not work if the last condition parsed evaluates to true, in this case the else case is executed */
    expdesc e;
    init_exp(&e, VJMP, 0);  /* what am I doing here ? */
    luaK_concat(fs, &flist, luaK_jump(fs));
    luaK_patchtohere(fs, escapelist);
    luaK_goiffalse(fs, &e);
    escapelist = e.f;
    luaX_next(ls);  /* skip FINALLY (after patch, for correct line info) */
    block(ls);  /* `finally' part */
  if (ls->t.token == TK_ELSE) {
    luaK_concat(fs, &escapelist, luaK_jump(fs));
    luaK_patchtohere(fs, flist);
    luaX_next(ls);  /* skip ELSE (after patch, for correct line info) */
    block(ls);  /* `else' part */
    luaK_concat(fs, &escapelist, flist);
  luaK_patchtohere(fs, escapelist);
  check_match(ls, TK_FI, TK_END, line);