|
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); } |