日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转lua解释执行脚本流程

發布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转lua解释执行脚本流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文轉自:http://www.cnblogs.com/zxh1210603696/p/4458473.html



#include "lua.hpp"#include <iostream> using namespace std;#pragma comment(lib, "lua5.1.lib")struct lua_guard{lua_State *pL;lua_guard(lua_State *s) :pL(s){}~lua_guard(){ lua_close(pL); } };int main(){lua_guard g(lua_open());luaL_openlibs(g.pL);int err;if ((err = luaL_dofile(g.pL, "mylua.lua") != 0)){throw runtime_error("open lua file error");}system("pause");return 0; }

首先利用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進行不同的過程

void luaV_execute (lua_State *L, int nexeccalls) {LClosure *cl;StkId base;TValue *k;const Instruction *pc;reentry: /* entry point */lua_assert(isLua(L->ci));pc = L->savedpc;cl = &clvalue(L->ci->func)->l;base = L->base;k = cl->p->k;/* main loop of interpreter */for (;;) {const Instruction i = *pc++;StkId ra;if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L, pc);if (L->status == LUA_YIELD) { /* did hook yield? */L->savedpc = pc - 1;return;}base = L->base;}/* warning!! several calls may realloc the stack and invalidate `ra' */ra = RA(i);lua_assert(base == L->base && L->base == L->ci->base);lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);lua_assert(L->top == L->ci->top || luaG_checkopenop(i));switch (GET_OPCODE(i)) {case OP_MOVE: {setobjs2s(L, ra, RB(i));continue;}case OP_LOADK: {setobj2s(L, ra, KBx(i));continue;}case OP_LOADBOOL: {setbvalue(ra, GETARG_B(i));if (GETARG_C(i)) pc++; /* skip next instruction (if C) */continue;}case OP_LOADNIL: {TValue *rb = RB(i);do {setnilvalue(rb--);} while (rb >= ra);continue;}case OP_GETUPVAL: {int b = GETARG_B(i);setobj2s(L, ra, cl->upvals[b]->v);continue;}case OP_GETGLOBAL: {TValue g;TValue *rb = KBx(i);sethvalue(L, &g, cl->env);lua_assert(ttisstring(rb));Protect(luaV_gettable(L, &g, rb, ra));continue;}case OP_GETTABLE: {Protect(luaV_gettable(L, RB(i), RKC(i), ra));continue;}case OP_SETGLOBAL: {TValue g;sethvalue(L, &g, cl->env);lua_assert(ttisstring(KBx(i)));Protect(luaV_settable(L, &g, KBx(i), ra));continue;}case OP_SETUPVAL: {UpVal *uv = cl->upvals[GETARG_B(i)];setobj(L, uv->v, ra);luaC_barrier(L, uv, ra);continue;}case OP_SETTABLE: {Protect(luaV_settable(L, ra, RKB(i), RKC(i)));continue;}case OP_NEWTABLE: {int b = GETARG_B(i);int c = GETARG_C(i);sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));Protect(luaC_checkGC(L));continue;}case OP_SELF: {StkId rb = RB(i);setobjs2s(L, ra+1, rb);Protect(luaV_gettable(L, rb, RKC(i), ra));continue;}case OP_ADD: {arith_op(luai_numadd, TM_ADD);continue;}case OP_SUB: {arith_op(luai_numsub, TM_SUB);continue;}case OP_MUL: {arith_op(luai_nummul, TM_MUL);continue;}case OP_DIV: {arith_op(luai_numdiv, TM_DIV);continue;}case OP_MOD: {arith_op(luai_nummod, TM_MOD);continue;}case OP_POW: {arith_op(luai_numpow, TM_POW);continue;}case OP_UNM: {TValue *rb = RB(i);if (ttisnumber(rb)) {lua_Number nb = nvalue(rb);setnvalue(ra, luai_numunm(nb));}else {Protect(Arith(L, ra, rb, rb, TM_UNM));}continue;}case OP_NOT: {int res = l_isfalse(RB(i)); /* next assignment may change this value */setbvalue(ra, res);continue;}case OP_LEN: {const TValue *rb = RB(i);switch (ttype(rb)) {case LUA_TTABLE: {setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));break;}case LUA_TSTRING: {setnvalue(ra, cast_num(tsvalue(rb)->len));break;}default: { /* try metamethod */Protect(if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))luaG_typeerror(L, rb, "get length of");)}}continue;}case OP_CONCAT: {int b = GETARG_B(i);int c = GETARG_C(i);Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));setobjs2s(L, RA(i), base+b);continue;}case OP_JMP: {dojump(L, pc, GETARG_sBx(i));continue;}case OP_EQ: {TValue *rb = RKB(i);TValue *rc = RKC(i);Protect(if (equalobj(L, rb, rc) == GETARG_A(i))dojump(L, pc, GETARG_sBx(*pc));)pc++;continue;}case OP_LT: {Protect(if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))dojump(L, pc, GETARG_sBx(*pc));)pc++;continue;}case OP_LE: {Protect(if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))dojump(L, pc, GETARG_sBx(*pc));)pc++;continue;}case OP_TEST: {if (l_isfalse(ra) != GETARG_C(i))dojump(L, pc, GETARG_sBx(*pc));pc++;continue;}case OP_TESTSET: {TValue *rb = RB(i);if (l_isfalse(rb) != GETARG_C(i)) {setobjs2s(L, ra, rb);dojump(L, pc, GETARG_sBx(*pc));}pc++;continue;}case OP_CALL: {int b = GETARG_B(i);int nresults = GETARG_C(i) - 1;if (b != 0) L->top = ra+b; /* else previous instruction set top */L->savedpc = pc;switch (luaD_precall(L, ra, nresults)) {case PCRLUA: {nexeccalls++;goto reentry; /* restart luaV_execute over new Lua function */}case PCRC: {/* it was a C function (`precall' called it); adjust results */if (nresults >= 0) L->top = L->ci->top;base = L->base;continue;}default: {return; /* yield */}}}case OP_TAILCALL: {int b = GETARG_B(i);if (b != 0) L->top = ra+b; /* else previous instruction set top */L->savedpc = pc;lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);switch (luaD_precall(L, ra, LUA_MULTRET)) {case PCRLUA: {/* tail call: put new frame in place of previous one */CallInfo *ci = L->ci - 1; /* previous frame */int aux;StkId func = ci->func;StkId pfunc = (ci+1)->func; /* previous function index */if (L->openupval) luaF_close(L, ci->base);L->base = ci->base = ci->func + ((ci+1)->base - pfunc);for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */setobjs2s(L, func+aux, pfunc+aux);ci->top = L->top = func+aux; /* correct top */lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);ci->savedpc = L->savedpc;ci->tailcalls++; /* one more call lost */L->ci--; /* remove new frame */ goto reentry;}case PCRC: { /* it was a C function (`precall' called it) */base = L->base;continue;}default: {return; /* yield */}}}case OP_RETURN: {int b = GETARG_B(i);if (b != 0) L->top = ra+b-1;if (L->openupval) luaF_close(L, base);L->savedpc = pc;b = luaD_poscall(L, ra);if (--nexeccalls == 0) /* was previous function running `here'? */return; /* no: return */else { /* yes: continue its execution */if (b) L->top = L->ci->top;lua_assert(isLua(L->ci));lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);goto reentry;}}case OP_FORLOOP: {lua_Number step = nvalue(ra+2);lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */lua_Number limit = nvalue(ra+1);if (luai_numlt(0, step) ? luai_numle(idx, limit): luai_numle(limit, idx)) {dojump(L, pc, GETARG_sBx(i)); /* jump back */setnvalue(ra, idx); /* update internal index... */setnvalue(ra+3, idx); /* ...and external index */}continue;}case OP_FORPREP: {const TValue *init = ra;const TValue *plimit = ra+1;const TValue *pstep = ra+2;L->savedpc = pc; /* next steps may throw errors */if (!tonumber(init, ra))luaG_runerror(L, LUA_QL("for") " initial value must be a number");else if (!tonumber(plimit, ra+1))luaG_runerror(L, LUA_QL("for") " limit must be a number");else if (!tonumber(pstep, ra+2))luaG_runerror(L, LUA_QL("for") " step must be a number");setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));dojump(L, pc, GETARG_sBx(i));continue;}case OP_TFORLOOP: {StkId cb = ra + 3; /* call base */setobjs2s(L, cb+2, ra+2);setobjs2s(L, cb+1, ra+1);setobjs2s(L, cb, ra);L->top = cb+3; /* func. + 2 args (state and index) */Protect(luaD_call(L, cb, GETARG_C(i)));L->top = L->ci->top;cb = RA(i) + 3; /* previous call may change the stack */if (!ttisnil(cb)) { /* continue loop? */setobjs2s(L, cb-1, cb); /* save control variable */dojump(L, pc, GETARG_sBx(*pc)); /* jump back */}pc++;continue;}case OP_SETLIST: {int n = GETARG_B(i);int c = GETARG_C(i);int last;Table *h;if (n == 0) {n = cast_int(L->top - ra) - 1;L->top = L->ci->top;}if (c == 0) c = cast_int(*pc++);runtime_check(L, ttistable(ra));h = hvalue(ra);last = ((c-1)*LFIELDS_PER_FLUSH) + n;if (last > h->sizearray) /* needs more space? */luaH_resizearray(L, h, last); /* pre-alloc it at once */for (; n > 0; n--) {TValue *val = ra+n;setobj2t(L, luaH_setnum(L, h, last--), val); luaC_barriert(L, h, val);}continue;}case OP_CLOSE: {luaF_close(L, ra);continue;}case OP_CLOSURE: {Proto *p;Closure *ncl;int nup, j;p = cl->p->p[GETARG_Bx(i)];nup = p->nups;ncl = luaF_newLclosure(L, nup, cl->env);ncl->l.p = p;for (j=0; j<nup; j++, pc++) {if (GET_OPCODE(*pc) == OP_GETUPVAL)ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];else {lua_assert(GET_OPCODE(*pc) == OP_MOVE);ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));}}setclvalue(L, ra, ncl);Protect(luaC_checkGC(L));continue;}case OP_VARARG: {int b = GETARG_B(i) - 1;int j;CallInfo *ci = L->ci;int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;if (b == LUA_MULTRET) {Protect(luaD_checkstack(L, n));ra = RA(i); /* previous call may change the stack */b = n;L->top = ra + n;}for (j = 0; j < b; j++) {if (j < n) {setobjs2s(L, ra + j, ci->base - n + j);}else {setnilvalue(ra + j);}}continue;}}} }

?

轉載于:https://www.cnblogs.com/zhangdongsheng/p/8603355.html

總結

以上是生活随笔為你收集整理的转lua解释执行脚本流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。