zoukankan      html  css  js  c++  java
  • lua解释执行脚本流程

     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 }
  • 相关阅读:
    ArcGIS Engine 常用方法(转)
    正则表达式 C#System.Text.RegularExpressions.Regex
    ae中栅格数据转为矢量数据 (转)
    ArcEngine 渲染的使用 (转)
    C#字符串分割成数组,中间多空格
    <C++ GUI Programming with Qt4 ,Second Edition> 学习笔记
    perl module and its package
    static_cast reinterpret_cast
    阅读<inside the c++ object modle > 有感
    C++ virtual table
  • 原文地址:https://www.cnblogs.com/zxh1210603696/p/4458473.html
Copyright © 2011-2022 走看看