1 #include "lua.hpp" 2 3 #include <iostream> 4 using namespace std; 5 6 #pragma comment(lib, "lua5.1.lib") 7 8 struct lua_guard{ 9 lua_State *pL; 10 lua_guard(lua_State *s) :pL(s){} 11 ~lua_guard(){ lua_close(pL); } 12 }; 13 14 int main(){ 15 lua_guard g(lua_open()); 16 luaL_openlibs(g.pL); 17 int err; 18 if ((err = luaL_dofile(g.pL, "mylua.lua") != 0)){ 19 throw runtime_error("open lua file error"); 20 } 21 system("pause"); 22 return 0; 23 }
首先利用lua提供的函数luaL_dofile来执行一个lua脚本。
可以看到有两个过程,首先luaL_loadfile函数将lua文件加载进来然后进行词法语法语义分析,得到一个closure函数放入栈中,接着调用lua_pcall函数来执行栈顶的closure。
我们先来看看第一个过程:
首先在luaL_loadfile中真正加载lua文件的是lua_load函数
在lua_load中调用了luaD_protectedparser来进行parse过程
在luaD_protectedparser中又调用了f_parser
在f_parser中根据一些选择来分别处理不同的情况,我们示例中会跑到luaY_parser函数中去,在luaY_parser中会调用luaX_next进行分析,这个函数会首先读取源文件中的第一个token
最后在luaX_next中调用了llex,llex是真正切出token的例程
在读取了第一个token后luaX_next返回,相关的词法信息保存在了lexstate中,接着luaY_parser调用chunk函数来递归的生成一个chunk块
在chunk中循环读取下一个token并根据token的类型一层一层的递归的生成chunk,将chunks根据层次组合成tree,位于root的是最外层chunk
在分析完lua脚本后会返回到f_parser,在f_parser中接着调用luaF_newLclosure来将分析结果包裹成一个closure然后push到lua栈中
接下来分析第二个过程:
当第一个过程完成后lua栈顶存放着一个closure,luaL_dofile中调用lua_pcall让其来调用这个closure:
在lua_pcall中调用了f_call
f_call中又接着调用了luaD_call,传入了被调用的closure和参数个数
最后在luaD_call中调用了luaV_execute来执行closure中的opcode
luaV_execute既是lua虚拟机执行opcode的函数,其中可以看到一个无限循环,利用switch (GET_OPCODE(i))来根据不同的opcode进行不同的过程
1 void luaV_execute (lua_State *L, int nexeccalls) { 2 LClosure *cl; 3 StkId base; 4 TValue *k; 5 const Instruction *pc; 6 reentry: /* entry point */ 7 lua_assert(isLua(L->ci)); 8 pc = L->savedpc; 9 cl = &clvalue(L->ci->func)->l; 10 base = L->base; 11 k = cl->p->k; 12 /* main loop of interpreter */ 13 for (;;) { 14 const Instruction i = *pc++; 15 StkId ra; 16 if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && 17 (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { 18 traceexec(L, pc); 19 if (L->status == LUA_YIELD) { /* did hook yield? */ 20 L->savedpc = pc - 1; 21 return; 22 } 23 base = L->base; 24 } 25 /* warning!! several calls may realloc the stack and invalidate `ra' */ 26 ra = RA(i); 27 lua_assert(base == L->base && L->base == L->ci->base); 28 lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); 29 lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); 30 switch (GET_OPCODE(i)) { 31 case OP_MOVE: { 32 setobjs2s(L, ra, RB(i)); 33 continue; 34 } 35 case OP_LOADK: { 36 setobj2s(L, ra, KBx(i)); 37 continue; 38 } 39 case OP_LOADBOOL: { 40 setbvalue(ra, GETARG_B(i)); 41 if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ 42 continue; 43 } 44 case OP_LOADNIL: { 45 TValue *rb = RB(i); 46 do { 47 setnilvalue(rb--); 48 } while (rb >= ra); 49 continue; 50 } 51 case OP_GETUPVAL: { 52 int b = GETARG_B(i); 53 setobj2s(L, ra, cl->upvals[b]->v); 54 continue; 55 } 56 case OP_GETGLOBAL: { 57 TValue g; 58 TValue *rb = KBx(i); 59 sethvalue(L, &g, cl->env); 60 lua_assert(ttisstring(rb)); 61 Protect(luaV_gettable(L, &g, rb, ra)); 62 continue; 63 } 64 case OP_GETTABLE: { 65 Protect(luaV_gettable(L, RB(i), RKC(i), ra)); 66 continue; 67 } 68 case OP_SETGLOBAL: { 69 TValue g; 70 sethvalue(L, &g, cl->env); 71 lua_assert(ttisstring(KBx(i))); 72 Protect(luaV_settable(L, &g, KBx(i), ra)); 73 continue; 74 } 75 case OP_SETUPVAL: { 76 UpVal *uv = cl->upvals[GETARG_B(i)]; 77 setobj(L, uv->v, ra); 78 luaC_barrier(L, uv, ra); 79 continue; 80 } 81 case OP_SETTABLE: { 82 Protect(luaV_settable(L, ra, RKB(i), RKC(i))); 83 continue; 84 } 85 case OP_NEWTABLE: { 86 int b = GETARG_B(i); 87 int c = GETARG_C(i); 88 sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); 89 Protect(luaC_checkGC(L)); 90 continue; 91 } 92 case OP_SELF: { 93 StkId rb = RB(i); 94 setobjs2s(L, ra+1, rb); 95 Protect(luaV_gettable(L, rb, RKC(i), ra)); 96 continue; 97 } 98 case OP_ADD: { 99 arith_op(luai_numadd, TM_ADD); 100 continue; 101 } 102 case OP_SUB: { 103 arith_op(luai_numsub, TM_SUB); 104 continue; 105 } 106 case OP_MUL: { 107 arith_op(luai_nummul, TM_MUL); 108 continue; 109 } 110 case OP_DIV: { 111 arith_op(luai_numdiv, TM_DIV); 112 continue; 113 } 114 case OP_MOD: { 115 arith_op(luai_nummod, TM_MOD); 116 continue; 117 } 118 case OP_POW: { 119 arith_op(luai_numpow, TM_POW); 120 continue; 121 } 122 case OP_UNM: { 123 TValue *rb = RB(i); 124 if (ttisnumber(rb)) { 125 lua_Number nb = nvalue(rb); 126 setnvalue(ra, luai_numunm(nb)); 127 } 128 else { 129 Protect(Arith(L, ra, rb, rb, TM_UNM)); 130 } 131 continue; 132 } 133 case OP_NOT: { 134 int res = l_isfalse(RB(i)); /* next assignment may change this value */ 135 setbvalue(ra, res); 136 continue; 137 } 138 case OP_LEN: { 139 const TValue *rb = RB(i); 140 switch (ttype(rb)) { 141 case LUA_TTABLE: { 142 setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); 143 break; 144 } 145 case LUA_TSTRING: { 146 setnvalue(ra, cast_num(tsvalue(rb)->len)); 147 break; 148 } 149 default: { /* try metamethod */ 150 Protect( 151 if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) 152 luaG_typeerror(L, rb, "get length of"); 153 ) 154 } 155 } 156 continue; 157 } 158 case OP_CONCAT: { 159 int b = GETARG_B(i); 160 int c = GETARG_C(i); 161 Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); 162 setobjs2s(L, RA(i), base+b); 163 continue; 164 } 165 case OP_JMP: { 166 dojump(L, pc, GETARG_sBx(i)); 167 continue; 168 } 169 case OP_EQ: { 170 TValue *rb = RKB(i); 171 TValue *rc = RKC(i); 172 Protect( 173 if (equalobj(L, rb, rc) == GETARG_A(i)) 174 dojump(L, pc, GETARG_sBx(*pc)); 175 ) 176 pc++; 177 continue; 178 } 179 case OP_LT: { 180 Protect( 181 if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) 182 dojump(L, pc, GETARG_sBx(*pc)); 183 ) 184 pc++; 185 continue; 186 } 187 case OP_LE: { 188 Protect( 189 if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) 190 dojump(L, pc, GETARG_sBx(*pc)); 191 ) 192 pc++; 193 continue; 194 } 195 case OP_TEST: { 196 if (l_isfalse(ra) != GETARG_C(i)) 197 dojump(L, pc, GETARG_sBx(*pc)); 198 pc++; 199 continue; 200 } 201 case OP_TESTSET: { 202 TValue *rb = RB(i); 203 if (l_isfalse(rb) != GETARG_C(i)) { 204 setobjs2s(L, ra, rb); 205 dojump(L, pc, GETARG_sBx(*pc)); 206 } 207 pc++; 208 continue; 209 } 210 case OP_CALL: { 211 int b = GETARG_B(i); 212 int nresults = GETARG_C(i) - 1; 213 if (b != 0) L->top = ra+b; /* else previous instruction set top */ 214 L->savedpc = pc; 215 switch (luaD_precall(L, ra, nresults)) { 216 case PCRLUA: { 217 nexeccalls++; 218 goto reentry; /* restart luaV_execute over new Lua function */ 219 } 220 case PCRC: { 221 /* it was a C function (`precall' called it); adjust results */ 222 if (nresults >= 0) L->top = L->ci->top; 223 base = L->base; 224 continue; 225 } 226 default: { 227 return; /* yield */ 228 } 229 } 230 } 231 case OP_TAILCALL: { 232 int b = GETARG_B(i); 233 if (b != 0) L->top = ra+b; /* else previous instruction set top */ 234 L->savedpc = pc; 235 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); 236 switch (luaD_precall(L, ra, LUA_MULTRET)) { 237 case PCRLUA: { 238 /* tail call: put new frame in place of previous one */ 239 CallInfo *ci = L->ci - 1; /* previous frame */ 240 int aux; 241 StkId func = ci->func; 242 StkId pfunc = (ci+1)->func; /* previous function index */ 243 if (L->openupval) luaF_close(L, ci->base); 244 L->base = ci->base = ci->func + ((ci+1)->base - pfunc); 245 for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ 246 setobjs2s(L, func+aux, pfunc+aux); 247 ci->top = L->top = func+aux; /* correct top */ 248 lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); 249 ci->savedpc = L->savedpc; 250 ci->tailcalls++; /* one more call lost */ 251 L->ci--; /* remove new frame */ 252 goto reentry; 253 } 254 case PCRC: { /* it was a C function (`precall' called it) */ 255 base = L->base; 256 continue; 257 } 258 default: { 259 return; /* yield */ 260 } 261 } 262 } 263 case OP_RETURN: { 264 int b = GETARG_B(i); 265 if (b != 0) L->top = ra+b-1; 266 if (L->openupval) luaF_close(L, base); 267 L->savedpc = pc; 268 b = luaD_poscall(L, ra); 269 if (--nexeccalls == 0) /* was previous function running `here'? */ 270 return; /* no: return */ 271 else { /* yes: continue its execution */ 272 if (b) L->top = L->ci->top; 273 lua_assert(isLua(L->ci)); 274 lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); 275 goto reentry; 276 } 277 } 278 case OP_FORLOOP: { 279 lua_Number step = nvalue(ra+2); 280 lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ 281 lua_Number limit = nvalue(ra+1); 282 if (luai_numlt(0, step) ? luai_numle(idx, limit) 283 : luai_numle(limit, idx)) { 284 dojump(L, pc, GETARG_sBx(i)); /* jump back */ 285 setnvalue(ra, idx); /* update internal index... */ 286 setnvalue(ra+3, idx); /* ...and external index */ 287 } 288 continue; 289 } 290 case OP_FORPREP: { 291 const TValue *init = ra; 292 const TValue *plimit = ra+1; 293 const TValue *pstep = ra+2; 294 L->savedpc = pc; /* next steps may throw errors */ 295 if (!tonumber(init, ra)) 296 luaG_runerror(L, LUA_QL("for") " initial value must be a number"); 297 else if (!tonumber(plimit, ra+1)) 298 luaG_runerror(L, LUA_QL("for") " limit must be a number"); 299 else if (!tonumber(pstep, ra+2)) 300 luaG_runerror(L, LUA_QL("for") " step must be a number"); 301 setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); 302 dojump(L, pc, GETARG_sBx(i)); 303 continue; 304 } 305 case OP_TFORLOOP: { 306 StkId cb = ra + 3; /* call base */ 307 setobjs2s(L, cb+2, ra+2); 308 setobjs2s(L, cb+1, ra+1); 309 setobjs2s(L, cb, ra); 310 L->top = cb+3; /* func. + 2 args (state and index) */ 311 Protect(luaD_call(L, cb, GETARG_C(i))); 312 L->top = L->ci->top; 313 cb = RA(i) + 3; /* previous call may change the stack */ 314 if (!ttisnil(cb)) { /* continue loop? */ 315 setobjs2s(L, cb-1, cb); /* save control variable */ 316 dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ 317 } 318 pc++; 319 continue; 320 } 321 case OP_SETLIST: { 322 int n = GETARG_B(i); 323 int c = GETARG_C(i); 324 int last; 325 Table *h; 326 if (n == 0) { 327 n = cast_int(L->top - ra) - 1; 328 L->top = L->ci->top; 329 } 330 if (c == 0) c = cast_int(*pc++); 331 runtime_check(L, ttistable(ra)); 332 h = hvalue(ra); 333 last = ((c-1)*LFIELDS_PER_FLUSH) + n; 334 if (last > h->sizearray) /* needs more space? */ 335 luaH_resizearray(L, h, last); /* pre-alloc it at once */ 336 for (; n > 0; n--) { 337 TValue *val = ra+n; 338 setobj2t(L, luaH_setnum(L, h, last--), val); 339 luaC_barriert(L, h, val); 340 } 341 continue; 342 } 343 case OP_CLOSE: { 344 luaF_close(L, ra); 345 continue; 346 } 347 case OP_CLOSURE: { 348 Proto *p; 349 Closure *ncl; 350 int nup, j; 351 p = cl->p->p[GETARG_Bx(i)]; 352 nup = p->nups; 353 ncl = luaF_newLclosure(L, nup, cl->env); 354 ncl->l.p = p; 355 for (j=0; j<nup; j++, pc++) { 356 if (GET_OPCODE(*pc) == OP_GETUPVAL) 357 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; 358 else { 359 lua_assert(GET_OPCODE(*pc) == OP_MOVE); 360 ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); 361 } 362 } 363 setclvalue(L, ra, ncl); 364 Protect(luaC_checkGC(L)); 365 continue; 366 } 367 case OP_VARARG: { 368 int b = GETARG_B(i) - 1; 369 int j; 370 CallInfo *ci = L->ci; 371 int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; 372 if (b == LUA_MULTRET) { 373 Protect(luaD_checkstack(L, n)); 374 ra = RA(i); /* previous call may change the stack */ 375 b = n; 376 L->top = ra + n; 377 } 378 for (j = 0; j < b; j++) { 379 if (j < n) { 380 setobjs2s(L, ra + j, ci->base - n + j); 381 } 382 else { 383 setnilvalue(ra + j); 384 } 385 } 386 continue; 387 } 388 } 389 } 390 }