本文转自: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解释执行脚本流程相关推荐

  1. c语言程序编译与烧录,一种解释自定义脚本并烧录的方法与流程

    本发明属于芯片烧录技术领域,特别涉及一种通过脚本进行芯片烧录的方法. 背景技术: 目前的烧录芯片主要是通过烧录器将烧录文件进行烧录,芯片中才会存储相应的代码.烧录文件有许多格式,如BIN文件,HEX文 ...

  2. asp服务器端作用,ASP中的服务器端脚本代码由()解释执行。 - 问答库

    问题: [单选] ASP中的服务器端脚本代码由()解释执行. A . WEB服务器 B . 应用程序服务器 C . 浏览器 D . 专用的浏览器插件程序 Cookie的应用是通过()对象和()对象来实 ...

  3. 吉里吉里1/吉里吉里2中KAG脚本的解释执行(1)

    从我开始关注吉里吉里2这个引擎开始,就一直看到关于"KAG的执行效率比TJS2低很多"的说法.但是到底慢多少呢?没见到过具体测评. 有机会的话我看看设计一个测评方法好了.关键是看看 ...

  4. python语言是解释执行的、因此执行速度比编译型语言慢_解释型语言的特点与理解...

    解释型语言是什么?对比编译型语言有什么区别? 为了将高级语言转换成计算机能识别的机器语言,需要一个'翻译'过程.即编译或者解释 编译型语言 编译型语言的程序只要经过编译器编译之后, 每次运行程序都可以 ...

  5. 2. sed执行的流程

    2.sed执行的流程sed命令 rhce sed脚本执行的步骤很容易记住:读取(Read),执行(Execute),打印(Print),重复(Repeat).我们可以利用这几个步骤的首字母REPR来记 ...

  6. 查看linux中的sh指向哪,什么是Linux的Shell脚本和怎么执行脚本?

    1.什么是Shell?shell shell是外壳的意思,就是操做系统的外壳.咱们能够经过shell命令来操做和控制操做系统,好比Linux中的Shell命令就包括ls.cd.pwd等等.总结来讲,S ...

  7. 3d 强制添加脚本_每日学点---Jenkins执行脚本权限问题

    问题: Jenkins执行shell时提示权限不够 和 sudo:没有终端存在,且未指定 askpass 程序 解释 Jenkins服务是默认是jenkins用户启动的,权限较小,需要赋予sudo权限 ...

  8. PHP-7.1 源代码学习:字节码在 Zend 虚拟机中的解释执行 之 概述

    本文简要介绍 zend 虚拟机解释执行字节码的基本逻辑以及相关的数据结构,关于 PHP 源代码的下载,编译,调试可以参考之前的系列文章 execute_ex 我们来看看执行一个简单的脚本 test.p ...

  9. ./ . 和#!/bin/bash 辨析Linux如何选择当前执行脚本的shell

    最近遇到一个有趣的问题,让我搞清楚Linux如何选择当前执行脚本的shell 执行cts的的 media stress test 需要安装 android-cts-media-1.0.zip 把这个文 ...

最新文章

  1. JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]
  2. 因修改/etc/sudoers权限导致sudo和su不能使用的解决方法
  3. 乡村振兴谋定齐鲁样板-农业大健康·周荣江:国情讲坛创新
  4. Windows下提升进程权限(转)
  5. 1018. 锤子剪刀布 (20)
  6. dram和nand哪个难生产_终于有人说清楚了什么是DRAM、什么是NAND Flash
  7. Android 自定义标尺滑动选择值
  8. UEFI开发与调试---ImageHandle和ControllerHandle
  9. AE导出透明背景gif
  10. 电脑壁纸桌面放计算机,电脑壁纸
  11. 如何将arcgis中shape要素文件转为mapgis中点线面
  12. 五个核心能力打造普惠金融商业化发展模式
  13. Excel可以将中文翻译成英文
  14. python数据处理2: 拟合数据、整合数据、导出数据
  15. 使用snmpwalk采集设备的OID信息
  16. 点集拓扑学(1)——度量空间
  17. 微信小程序--企业认证篇
  18. 【对软件项目的一些理解】多维团队分工合作模式
  19. GaussDB架构(中)
  20. 记录 |探究一次嗅到坏代码后封装再封装

热门文章

  1. 一步一步学NUnit
  2. psp前景与范围文档
  3. webservice-WebService试题
  4. Hibernate查询缓存
  5. koa --- jwt实现最简单的Token认证
  6. es6 --- String.prototype.padStart
  7. javascript --- 优先级执行顺序
  8. bootstrap --- 表单
  9. wdk1703+vs2015编译的诡异问题
  10. Linux下进行Web服务器压力(并发)测试工具http_load、webbench、ab、Siege、autobench简单使用教程(转)...