lua if条件语句的实现

本文探讨了 Lua 语言中 if 条件语句的实现,从字节码和词法分析的角度进行了解析。通过断点调试虚拟机的 luaV_execute 函数,揭示了 if 语句的执行流程,以及字节码如何根据条件决定程序的执行路径。此外,还介绍了词法分析在生成代码过程中的作用。

先来看看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的分析,

下面的还真是不知道怎么组织,还是未完待续吧......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值