《lua设计与实现》第6章 指令的解析与执行--6.4 函数相关的操作指令
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了《lua设计与实现》第6章 指令的解析与执行--6.4 函数相关的操作指令,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3079字,纯文字阅读大概需要5分钟。
内容图文
![《lua设计与实现》第6章 指令的解析与执行--6.4 函数相关的操作指令](/upload/InfoBanner/zyjiaocheng/1304/89975383ac5b4cb58d088a4fb372eafc.jpg)
在下面的示例中,(3)的prev成员(2),(2)的prev成员(1),(1)的prev成为NULL。
g = 10-- (1) 全局环境的 FuncState: 其 prev 为 NULLfunction fun () -- (2) fun 的 FuncState: 其 prev 指向(1)local a = 2function test() -- (3) test 的 FuncState: 其 prev 指向(2)local b = 1-- g -> test -> fun -> 全局环境 -> VGLOBAL-- b -> test ->VLOCAL-- a -> test -> fun -> VUPVALprint(a,b,g) end test() end fun()
Lua解释器在解析完某个环境(比如全局环境)中定义的函数之后,生成的 Proto 结构体数据必然也会存放在该环境的 Proto结构体数组中,最后一并返回。测试代码:
function test() end
ChunkSpy编译出来的指令如下。第一层函数即全局环境,这一层的第一条指令是一个closure语句,用于定义函数;紧跟着是一条setglobal指令,用于将函数体的信息、赋值给第二层的函数test。
; function [0] definition (level 1) ; 0 upvalues, 0 params, 2 stacks .function0022 .const "test" ; 0 ; function [0] definition (level 2) ; 0 upvalues, 0 params, 2 stacks .function0002 [1] return 01 ; end of function [1] closure 00 ; 0 upvalues [2] setglobal 00 ; test [3] return 01 ; end of function
函数定义相关指令 OP_CLOSURE 格式如下:
typedef enum { /*A: 存放函数的寄存器 B: Proto数组的索引 C: 无 */// ...... OP_CLOSURE,/*A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))*/// ...... } OpCode;
解释器会依次走过以下函数(箭头左方),右边是其对应的EBNF表示
chunk -> {stat [‘;‘]} stat -> funcstat funcstat -> FUNCTION funcname body
函数调用堆栈,funcstat处理函数的定义,即如何把函数体信息和变量结合在一起;body处理函数体的解析。
int dofile(constchar *filename, constchar *cmd); LUALIB_API int luaL_loadfile (lua_State *L, constchar *filename); LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, constchar *chunkname); int luaD_protectedparser (lua_State *L, ZIO *z, constchar *name); int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, ptrdiff_t ef); int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); staticvoid f_parser (lua_State *L, void *ud); Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, constchar *name); // EBNF 对应函数staticvoid chunk (LexState *ls); staticint statement (LexState *ls); staticvoid body (LexState *ls, expdesc *e, int needself, int line); staticvoid funcstat (LexState *ls, int line);
主要函数body
static void body (LexState *ls, expdesc *e, int needself, int line) { /* body -> `(‘ parlist `)‘ chunk END */ FuncState new_fs; open_func(ls, &new_fs); //主要用于初始化 new_fs //完成函数体的解析,解析结果保存在局部变量 new_fs 的 Proto *f 中 。 new_fs.f->linedefined = line; checknext(ls, ‘(‘); if (needself) { new_localvarliteral(ls, "self", 0); adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ‘)‘); chunk(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); //将最后分析的结果保存到 new_fs 的 Proto 中 close_func(ls); // 主要功能是把 new_fs 的 Proto 指针保存到父函数 FuncState 的 Proto指针的 p 数组中 pushclosure(ls, &new_fs, e); }
用于存放函数信息的结构体是Closure
#define ClosureHeader \ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; struct Table *env typedef struct CClosure { ClosureHeader; lua_CFunction f; TValue upvalue[1]; } CClosure; typedef struct LClosure { ClosureHeader; struct Proto *p; //用于存放解析函数体代码之后的指令 UpVal *upvals[1]; //用于保存外部引用的局部变量} LClosure; typedef union Closure { CClosure c; LClosure l; } Closure;
funcstat 函数
原文:https://www.cnblogs.com/yyqng/p/14773866.html
内容总结
以上是互联网集市为您收集整理的《lua设计与实现》第6章 指令的解析与执行--6.4 函数相关的操作指令全部内容,希望文章能够帮你解决《lua设计与实现》第6章 指令的解析与执行--6.4 函数相关的操作指令所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。