您的位置:首页 > 编程语言 > Lua

lua if条件语句的实现

2012-12-05 20:16 706 查看
先来看看lua if语句最简单的用法:

local n = 3
if n > 3 then
n = 4
else
n = 5
end


字节码

要分析lua如何通过词法(llex.c),语法(lparse.c),代码生成器(lcode.c)来解析上面这段代码,生成供虚拟机执行的字节码, 就得先知道这段lua代码最终究竟生成了什么模样的字节码。

先来一步步断点调试虚拟机的执行入口luaV_execute(lvm.c),发现上述代码执行流程为:

1:OP_LOADK ----> 2:OP_LE ---> 3:OP_LOADK ---> 4:OP_RETURN

就这4步。 第1步,第4步分别把3和4加载到n(加载到栈). 第4步就是退出函数了。第2步是条件语句的关键. 来看看OP_LE干了些啥工作:

void luaV_execute (lua_State *L, int nexeccalls) {
...
...
const Instruction i = *pc++;  // (1)
...
switch (GET_OPCODE(i)) {
case OP_LE: {
Protect(
if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))  // (2)B,C操作数比较多结果是否等于A操作数
dojump(L, pc, GETARG_sBx(*pc)); // 跳到指定指令
)
pc++;  // 跳过OP_JMP指令
continue;
...
}
...
}

(2)处拿出当前指令i的B,C操作数进行比较,与A操作数判等,如果相等就跳到PC指向的指令,从(1)看出*pc就是i的下条指令。 所以OP_JMP紧接到是OP_JMP指令,非LOADK.

如果不相等就pc指针再次加1跳过OP_JMP直接到下一条语句。所以上述简单的条件语句的虚拟字节码如下

1:OP_LOADK ----> 2:OP_LE ----> 3: OP_JMP ---> 4:OP_LOADK ---> 4:OP_RETURN

2号指令会判断条件,如果成立就再次把指令指针pc加一跳过3进入4,否则直接跳入4.

知道了if虚拟字节码接下来看看lua是怎么分析的。


词法分析,代码生成

if语法分析的入口:
static void ifstat (LexState *ls, int line) {
/* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
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) {
luaK_concat(fs, &escapelist, luaK_jump(fs));
luaK_patchtohere(fs, flist);
flist = test_then_block(ls);  /* ELSEIF cond THEN block */
}
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_END, TK_IF, line);
}


不分析else和elseif部分,test_then_block的代码如下:
static int test_then_block (LexState *ls) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
int condexit;
luaX_next(ls);  /* skip IF or ELSEIF */
condexit = cond(ls);
checknext(ls, TK_THEN);
block(ls);  /* `then' part */
return condexit;
}

static int cond (LexState *ls) {
/* cond -> exp */
expdesc v;
expr(ls, &v);  /* read condition */
if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */
luaK_goiftrue(ls->fs, &v);
return v.f;
}


在cond中通过expr函数对表达式进行分析,也即 表达式 n > 3的分析,

下面的还真是不知道怎么组织,还是未完待续吧......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐