lua函数定义
FuncState
proto结构数组保存函数原型信息;prev保存父函数体指针;actvar保存定义的局部变量;upvalues保存upvalue
Lua源码中,专门有一个结构体FuncState用来保存函数相关的信息.其实,即使没有创建任何函数,对于Lua而言也有一个最外层的FuncState数据.这个结构体的定义:
typedef struct FuncState {
  Proto *f;  /* current function header */
  Table *h;  /* table to find (and reuse) elements in  */
  struct FuncState *prev;  /* enclosing function */
  struct LexState *ls;  /* lexical state */
  struct lua_State *L;  /* copy of the Lua state */
  struct BlockCnt *bl;  /* chain of current blocks */
  int pc;  /* next position to code (equivalent to `ncode') */
  int lasttarget;   /* `pc' of last `jump target'  */
  int jpc;  /* list of pending jumps to `pc' */
  int freereg;  /* first free register */
  int nk;  /* number of elements in `k'  */
  int np;  /* number of elements in `p'  */
  short nlocvars;  /* number of elements in `locvars' */
  lu_byte nactvar;  /* number of active local variables  */
  upvaldesc upvalues[LUAI_MAXUPVALUES];  /* upvalues */
  unsigned short actvar[LUAI_MAXVARS];  /* declared-variable stack */
} FuncState;
其中的Proto结构体数组用于保存函数原型信息,包括函数体代码(opcode),之所以使用数组,是因为在某个函数内,可能存在多个局部函数.而prev指针就是指向这个函数的”父函数体”的指针.
比如以下代码:
function fun()
   function test()
   end
end
那么,在保存test函数原型的Proto数据就存放在保存fun函数的FuncState结构体的p数组中,反之,保存test函数的FuncState.prev指针就指向保存func函数的FuncState指针.
接着看Funcstate结构体的成员,actvar数组用于保存局部变量,比如函数的参数就是保存在这里.另外还有一个存放upval值的upvalues数组.这里有两种不同的处理.如果这个upval是父函数内的局部变量,则生成的是MOVE指令用于赋值;如果对于父函数而言也是它的upval,则生成GET_UPVAL指令用于赋值.
当开始处理一个函数的定义时,首先调用open_func函数,创建一个新的Proto结构体用于保存函数原型信息,接着将该函数的FuncState的prev指针指向父函数.
最后当函数处理完毕时,调用pushclosure函数将这个新的函数的信息push到父函数的Proto数组中.
函数也是第一类值 可以存在变量里
最后,由于函数在Lua中是所谓的”first class type”,所以其实以下两段Lua代码是等价的:
local function test()
  -- 可以test
end
--以上相当于 local test; test = function() ...  end
local test = function ()
   --不可以调用test 以为第一类之定义完成之后才可以使用
end
也就是说,其实是生成一段代码,用于保存函数test的相关信息,之后再将这些信息赋值给变量test,这里的test可以是local,也可以是global的,这一点跟一般的变量无异.
函数定义词法分析
所以在与函数定义相关的词法分析代码中:
static void funcstat (LexState *ls, int line) {
  /* funcstat -> FUNCTION funcname body */
  int needself;
  expdesc v, b;
  luaX_next(ls);  /* skip FUNCTION */
  needself = funcname(ls, &v);
  body(ls, &b, needself, line);
  luaK_storevar(ls->fs, &v, &b);
  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */
}
上面的变量v首先在funcname函数中获得该函数的函数名,变量b在进入函数body之后可以得到函数体相关的内容.在这之后的luaK_storevar调用,就是把b的值赋值给v,也就是前面提到的函数体赋值给函数名.
lua函数定义的更多相关文章
- lua os.date函数定义和示例
		os.date函数定义 原型:os.date ([format [, time]]) 解释:返回一个按format格式化日期.时间的字串或表. lua源码中os.date的注释如下: --- --- ... 
- Lua学习---函数定义
		1.函数定义的格式: Lua使用function定义函数,语法如下: function function_name (arc) --arc表示参数列表,函数的参数列表可以为空 --body end 上 ... 
- Lua函数之二
		Lua函数之二 Lua中函数的两个重要特性: 1.函数和其他类型(如number.string)一样,可以存放在变量中,也可以存放在table中,可以作为函数的参数,还可以作为函数的返回值. 2.嵌套 ... 
- C语言调用Lua函数
		记得上学时,初中英文课本中,上网叫做surfing the internet,中文叫网上冲浪. 那个时期,人们常常称互联网为赛博空间.现在工作了,大量的零碎时间用于上微博,知乎,QQ.这些碎片化的阅读 ... 
- Lua函数以及闭合函数的理解
		Lua函数以及闭合函数的理解 来源 http://blog.csdn.net/mydad353193052/article/details/48731467 词法域和第一类型 在C/C++,C#或者J ... 
- lua函数随记
		在大多数Lua语法分析中可以获得这些标准Lua函数. 无可争辩, 我们可以查阅Lua网站, 但是一些少了的函数被Blizzard进行了调整. 下面列出了所有Lua函数. WoW API中的Lua注意在 ... 
- Lua函数[转]
		在大多数Lua语法分析中可以获得这些标准Lua函数. 无可争辩, 我们可以查阅Lua网站, 但是一些少了的函数被Blizzard进行了调整. 下面列出了所有Lua函数. WoW API中的Lua注意在 ... 
- cocos2d-x 3.0 在C++中调用lua函数(2)
		个人觉得3.0里面, 在C++下面调用lua函数很不方便, 所以就扩展了一个类, 继承自LuaStack, 代码和使用方式如下: #ifndef __CC_LUA_STACKEX_H_ #define ... 
- cocos2d-x 3.0 在C++中调用lua函数
		代码用的是<cocos2d-x 3.0 在lua中调用自定义类>中的代码. 在上篇的基础上进行扩充. 写lua函数 local function process_packet(user_d ... 
随机推荐
- LOCAL_LISTENER 引起的错误
			1. 如果你的LOCAL_LISTENER 指定的是一个别名 比如L2 *.local_listener='L2' 启动实例的时候 会先到 tnsnames.ora 文件里取查找定义名为L2的TNS服 ... 
- C#判断奇偶数的函数
			// 现代流行的"程序员"public static bool IsOdd(int n) { while (true) { switch (n) ... 
- JAVA使用POI如何导出百万级别数据
			用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在6 ... 
- 关于springMVC的一些xml配置
			①springMVC必备jar包: commons-logging-1.1.3.jar spring-aop-4.0.0.RELEASE.jar spring-beans-4.0.0.RELEASE. ... 
- Python入门-模块2(sys模块、shutil 模块)
			sys模块: sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 s ... 
- Hadoop HBase概念学习系列之模式设计(十)
			Hbase与RDBMS的区别在于:HBase的Cell(每条数据记录中的数据项)是具有版本描述的(versioned),行是有序的,列(qualifier)在所属列簇(Column familie ... 
- September 25th 2017 Week 39th Monday
			No man is rich enough to buy back his own past. 没有人富有到可以赎回自己的过去. Those rich are not willing to buy b ... 
- DevExpress02、RibbonControl
			RibbonControl 常用操作 1.如何代码显示选中的页 ribbonControl1.SelectedPage = ribbonPage2; 2.如何绑定ApplicationMenus和Po ... 
- 自定义shell命令--闪烁的字母(PIL实现)
			之前看到shell命令行,有人写过漫天下字母的cmatrix,想自己动手用python写一个类似,但是比较有自己风格的shell屏保 大致效果如下: 制作这个的大体思路比较简单: 1.利用python ... 
- linux下如何实现mysql数据库每天自动备份定时备份
			版权声明:本文为 testcs_dn(微wx笑) 原创文章,非商用自由转载-保持署名-注明出处,谢谢. 目录(?)[+] 概述 备份是容灾的基础,是指为防止系统出现操作失误或系统故障导致数 ... 
