Request for help on extending if statement (lparser.c)

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Request for help on extending if statement (lparser.c)

Alexander Walz
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,

Alexander

-----------------------------------------------------------------------------

The extended if structure would look something like this:

Old                      New

if cond1 then            if cond1 then
    statement1              statement1
    statementX
    statementY
elseif cond2             elseif cond 2 then
    statement2              statement2
    statementX
    statementY
                         finally  -- will always be executed of one cond is true
                            statementX
                            statementY
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 */
  }
  else
    luaK_concat(fs, &escapelist, flist);
  luaK_patchtohere(fs, escapelist);
  check_match(ls, TK_FI, TK_END, line);
}

Reply | Threaded
Open this post in threaded view
|

Re: Request for help on extending if statement (lparser.c)

Sam Roberts
On Tue, Oct 27, 2009 at 3:01 PM, Alexander Walz <[hidden email]> wrote:
> 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.

Could you give an example of the syntax you want to implement? It
sounds like just using
and will work for you:

if cond
and condb
and condc
and condd
then
  equal_statements()
else
  other_statements()
end

You also might want to check out metalua as an easier way of hacking the syntax.

Cheers,
Sam
Reply | Threaded
Open this post in threaded view
|

Re: Request for help on extending if statement (lparser.c)

David Manura
In reply to this post by Alexander Walz
On Tue, Oct 27, 2009 at 6:01 PM, Alexander Walz wrote:
> Of course, statementsXY could be put into a procedure to be called from
> within the if statement.

or transformed via token filters, in a way that preserves line numbers
for debugging:

local _FINALLY; if cond1 then
   statement1
_FINALLY = true; elseif cond 2 then
   statement2;
_FINALLY = true; end; if _FINALLY then
   statementX
   statementY
else
   other statements
end
Reply | Threaded
Open this post in threaded view
|

Re: Request for help on extending if statement (lparser.c)

Klaus Ripke
In reply to this post by Alexander Walz
Hi

On Tue, Oct 27, 2009 at 11:01:55PM +0100, Alexander Walz wrote:

> The extended if structure would look something like this:
>
> Old                      New
>
> if cond1 then            if cond1 then
>    statement1              statement1
>    statementX
>    statementY
> elseif cond2             elseif cond 2 then
>    statement2              statement2
>    statementX
>    statementY
>                         finally  -- will always be executed of one cond
> is true
>                            statementX
>                            statementY
> else                     else
>    other statements        other statements
> end;                     end;

that should translate to something like:

local _else -- if_with_finally_clause
if cond1 then
...
else
        other statements
_else = true end if ~ _else then -- finally
        statementX
        statementY
end

Should be possible using the token filter.
Obviously the if cases must not contain a break or return.


In plain Lua I would prefer
repeat
if cond1 then
...
else
        other statements
        break
end
-- finally
statementX
statementY
until true



cheers
Reply | Threaded
Open this post in threaded view
|

Re: Request for help on extending if statement (lparser.c)

Luiz Henrique de Figueiredo
> repeat
> if cond1 then
> ...
> else
> other statements
> break
> end
> -- finally
> statementX
> statementY
> until true

You mean, until *false*, right?
Reply | Threaded
Open this post in threaded view
|

Re: Request for help on extending if statement (lparser.c)

Luiz Henrique de Figueiredo
> > repeat
> > until true
>
> You mean, until *false*, right?

Oops, never mind me -- you're right of course. Sorry for the noise.