lua
Shonm
用blog记录点点滴滴。。。成长的轨迹一步一个印
展开
-
lua 加载文件相关函数
重点掌握 require,dofile,loadfile,其他的了解即可。一、require 1.功能:载入文件并执行代码块,对于相同的文件只执行一次,即多次require时,只会执行一次文件的代码块 2.调用:require("filename").注意这里文件名不能包括后缀名,否则会提示找不到文件. 注:寻找文件的路径在package.path中,print(package.pat...原创 2018-03-22 15:23:50 · 1746 阅读 · 0 评论 -
一步步写lua解释器--代码生成
上一篇讲了如何生成语法树。生成语法树之后就要生成代码了,即可以被执行的指令,想想都有点激动。前面提到再复杂的代码都可以转换为赋值,运算,比较等指令。赋值是将一个确定的数值或字符串赋给一个变量,他是一个二元操作。运算无非是简单的四则运算,加减乘除,他们都是二元的。比较也是将值与true or false对比,也是二元操作。赋值拿local a = 1 举例,变量是a,值是1。遇到这个语句时,怎么...原创 2018-08-26 18:42:39 · 1448 阅读 · 0 评论 -
一步步写lua解释器--函数语句
函数包括函数名,参数,函数体。函数体又包括语句,返回语句。函数的声明又分为显式,匿名式,例如下面两种:local f = function(params) ... endlocal function f(params) ... end不管哪种类型,我们需要提取其名字f,保存在局部变量表里,这个倒是不难。然后是对函数的每个部分逐一解析。函数参数是名字变量列表,这个相当于初始化名字列表,...原创 2018-08-26 22:27:07 · 438 阅读 · 0 评论 -
一步步写lua解释器--闭包的处理
前面说到函数执行完毕,也就是闭包退出时,会清除其作用域的局部变量。但是有个问题就是保存闭包的上值,何为上值,举个简单的例子:local f = function(a) return function() a = a + 1 return a ...原创 2018-08-26 22:59:35 · 398 阅读 · 0 评论 -
一步步写lua解释器--if else语句
if 语句可以拆成三个部分:逻辑判断部分,if 左边的部分,if右边部分,例如:if b == 1 then local c = 100 print(c)else print(2)endb==1为逻辑判断部分local c=100 print(c)为if左边部分,print(2)为右边部分如果if 没有else 则右边部分为空。对于if a ...原创 2018-08-26 23:25:24 · 970 阅读 · 0 评论 -
一步步写lua解释器--table的实现
lua中的table貌似是lua中唯一的数据结构了,他既可以充当数组,也可以充当map使用,把这两种结合为一个数据结构,足以说明lua的简洁易用性。原本以为table实现起来会比较复杂,结果一上午就差不多写好了,而if语句却写了一整天,当然也包括了优化其他代码。table的实现包括构造和存取。一个table的构造:local a = {b = 3,c = {e = 9}}语法树...原创 2018-08-26 23:49:06 · 615 阅读 · 0 评论 -
一步步写lua解释器--数值for循环
lua中for语句分为数值型for循环和泛型for循环。其中数值型for较为简单,我们先说它。数值型for循环的要点:for var=exp1,exp2,exp3 do <执行体> end例如:for i = 1, 2,1 do print(i)end需要特别注意的是,其中变量i是这个for循环体的局部变量,也就是说这个i在for循环外...原创 2018-08-26 23:56:14 · 481 阅读 · 0 评论 -
一步步写lua解释器--泛型for循环
写泛型for之前,我发现连这个语法都不是太清晰,因为大都for, in 后面跟着pairs()或ipairs()函数,以为for,in后面只能是这两个函数。查看了官网资料,for, in 的语法规则是:for namelist in explist do block end 也就是说for,in后面需要一个表达式列表,但是他们必须要有一定的的规则,例如:for k,v in ip...原创 2018-08-27 00:03:23 · 749 阅读 · 0 评论 -
一步步写lua解释器--递归的bug
在网上与人讨论时,别人问我能否调用递归。这个确实还没有执行过,我也想试一试。结果一试就GG了。调试的结果是闭包内部的局部变量表push和pop的次数好像不一致,导致pop空表,然后就崩溃了。经过反复调试,还是没有找到问题,局部表的push和pop就在块开始和结束的地方,应该是没有问题的。调试是个非常复杂的过程,因为嵌套的调用非常多,一般递归里面肯定是由if语句的,而if语句又是写在块里面,逐渐...原创 2018-08-27 00:12:13 · 555 阅读 · 0 评论 -
一步步写lua解释器--多参赋值的问题
有个问题倒是缠绕了很多时间,问题非常简单清晰,就是,函数的返回值取值个数的问题。例如function ft() return 13, 78 endlocal a, b, c = 3, 4, ft()print(a, b,c)a, b, c = 3, ft(), 5print(a, b,c)a, b, c = ft(), 5print(a, b,c)a, b, c = ft...原创 2018-08-27 00:19:38 · 693 阅读 · 0 评论 -
一步步写lua解释器--开篇
本人去年开始接触lua,之后就被它简单的语法和恰到好处的功能给吸引住了。本人搞了几年的C++,深感C++的繁琐和深奥,后来接触了像python,javascript等脚本语言,学习到了函数式编程语言的精妙。听说lua语言源码短小精悍,于是打算研究一下源码。可是看到其源码才发现,没有编译原理基础的我寸步难行,看别人写分析lua源码的博客也是门路不对。后来决定恶补一下编译原理的知识,在网上看了一些...原创 2018-08-25 21:47:48 · 6653 阅读 · 0 评论 -
一步步写lua解释器--语法分析
当我们从源码中读取到一个个单词token之后,就需要将这些token转换为实际的语句了。一门语言的产生是有一定的道理,是用来解决实际问题的,没人会吃饱了没事干发明一门语言。例如在学数学时要求一个一元一次方程的结果即解方程ax + b = c,我们可以写如下代码:local f = funciton(a, b, c) if a ~= 0 then local x = (c - ...原创 2018-08-25 23:44:08 · 1460 阅读 · 4 评论 -
一步步写lua解释器--闭包的由来
原本函数在最开始的时候就实现了,但是后来发现了不少bug,都是由参数个数,返回值个数等引起的,比想象的要复杂一些。lua中函数与闭包是紧密相连的。我们早在学习c或java的的时候,就认识了函数,学习诸如lua,python,js脚本语言的时候才听说闭包这个词。在很长一段时间内我对闭包的概念都不是很理解,后来才慢慢清晰。现在亲自实现脚本语言后,才真正明白闭包的含义。简单一句话概括就是,函数是...原创 2018-08-25 23:55:19 · 462 阅读 · 0 评论 -
lua代码优化
前几天写代码lua时,由于涉及到大量的数值逻辑计算,所以性能至关重要。经过一番研究和调试,总结了如下提高lua代码执行效率的方法:使用缓存这个不论是在lua,在任何语言的程序中都适用,脚本语言显得尤为突出。使用缓存来优化,提高程序性能是一个很大的主题,这里不再详细论述。只需记得,当使用重复数据(或有重叠)时一定要缓存起来,以供后面使用,而不是每次都重新计算,这样会大大提高效率,尤其是涉及到繁...原创 2019-03-06 15:23:50 · 2494 阅读 · 2 评论 -
lua 迭代器的实现
lua迭代器的用法为:for k, v in (i)pairs(t) do print(k,v)end我们搞懂for...in做了什么的就明白上面代码的实现了。其实for..in后面需要一个迭代函数,该函数可以有两个参数,一个是状态常量,一个是控制变量。例如:local ipairsIter = function(t, i) i = i + 1 local ...原创 2018-07-20 12:34:36 · 427 阅读 · 0 评论 -
lua 热更新原理(一)
热更一般是针对模块的线上替换。我们动态加载要热更的模块试试。例如,我们在循环间隔加载某模块,这样就能有时间去更改模块了。测试的代码如下:for i = 1, 5 do local m = require('other') print('other.a is ', m.a) Sleep(5)end我们循环加载了other这个模块他仅仅返回一个local table...原创 2018-06-07 20:59:22 · 30426 阅读 · 5 评论 -
lua require机制
相信大家在lua中都用过require。为了达到代码复用和结构化的目的,各种语言都有require机制。lua的require看似简单,其实里面有很多玄机。一 require从哪里加载模块文件从虚拟机的path,cpath等全局变量中。虚拟机有默认的值,在变量package.path和package.cpath中。例如我打印的path,cpath分别为:path :/usr/loc...原创 2018-06-07 15:32:47 · 20923 阅读 · 1 评论 -
lua 协程代码执行流程
lua协程是比较高级的内容,代码执行流程比较复杂难懂,在这里分析一下.有如下代码co1 = coroutine.create( function ( ) print('at co1 a ') coroutine.resume(co2) print('at co1 b ') end)co2 = coroutine.create( function ( ) prin...原创 2018-03-24 17:55:47 · 1639 阅读 · 1 评论 -
lua协程场景分析
上一篇文章lua代码执行流程介绍了lua协程代码执行的流程,感觉这种写法不直观,难懂,我们知道存在即合理,那lua协程的合理又在哪里呢?实际又用在哪里呢,给开发带来哪些好处呢?这篇按照我的理解分析一下,不足之处请指正.有这样一个场景,服务器产生一些字符,然后客户端显示这些字符,即典型的生产者--消费者模式.直白的写法如下:function producer() return io....原创 2018-03-26 11:03:57 · 5432 阅读 · 1 评论 -
lua 和C交互相关函数
1 堆栈相关1.1int (lua_gettop) (lua_State *L); 【-0,+0】用于返回栈中元素的个数,同时也是栈顶元素的索引,因为栈底是1,所以栈中有多少个元素,栈顶索引就是多少;2.2void (lua_settop) (lua_State *L, int idx); 【-?,+?】把栈索引idx设置为栈...原创 2018-03-22 11:19:14 · 562 阅读 · 0 评论 -
lua5.3中luaL_setfunc设置upvalue的用法示例
缘起luaL_setfuncs 这个函数可以注册c函数到lua,另外还可以设置闭包函数使用的变量upvalue. 我没有用过,在 云风的skynet 才第一次见过,于是写个例子实际使用以下.函数原型:void luaL_setfuncs (lua_State L, const luaL_Reg l, int nup);文档定义:Registers all functions in the arra...转载 2018-03-27 09:34:05 · 1305 阅读 · 0 评论 -
lua 与c交互api
/*相关API:====lua_createtable 原型: void lua_createtable (lua_State *L, int narr, int nrec); 描述: 创建一个新的table并将之放在栈顶.narr是该table数组部分的长度,nrec是该table hash部分的长度. 当我们确切的知道要放多少元素到table的时候,使用这个函数,lua可以预分配一些...转载 2018-03-27 10:13:39 · 461 阅读 · 0 评论 -
lua协程相关参数与返回值
通过上两篇lua代码执行流程, lua协程场景分析的介绍,知道了协程的基本用法和场景.其实协程与协程之间是通过参数和返回值进行交互的.引用上篇的代码:coConsume = coroutine.create( function () while true do local stutas, msg = coroutine.resume(coProducer) print('rece...原创 2018-03-28 10:44:51 · 1224 阅读 · 0 评论 -
Lua的内存监测和回收
Lua内存是自动收集的, 这点跟Java类似, 不被任何对象或全局变量引用的数据,将被首先标记为回收,不需要开发者做任何事情.但是,正如Java也会有内存泄露一样, Lua也会有, 只不过,跟C++的不同,它是由于代码执行所装载的资源,并没有被彻底销毁而导致,其中,最臭名昭著的就是不小心把局部变量声明成了全局变量(忘了加local修饰符)。 类似这样造成的内存泄露, 跟任何其他语言的内存泄露一样,...转载 2018-03-28 15:21:01 · 443 阅读 · 0 评论 -
lua协程池
看云风老大的skynet源码,里面有创建协程池的写法.云大真是把lua技术玩的炉火纯青啊,不得不让人佩服.看到协程池这个名字就知道他是用来干嘛的,相信大家也见过线程池,内存池的概率和写法.因为创建这些资源是很费时间和内存的,所以预先创建一些这样的资源,或者重复利用已有的资源就可以达到提高程序运行的效率.下面就来分析一下lua协程池.local coroutine_pool = {}local ...原创 2018-03-28 15:52:16 · 2150 阅读 · 5 评论 -
Lua的面向对象设计1
这几天看了Lua程序设计,读懂面向对象设计后,发现真的好巧妙.Lua本身没有支持面向对象的特性,如像C++,java有class等关键字,Lua的面向对象完全是基于其自身的特性来模拟设计的,读懂之后不得不叹服.Lua的面向对象特性是基于其表和元表的特性来完成的,下面举例说明比如,我们要设计一个账户类,包含存钱(deposit())取钱(withdraw())的方法,还有余额(balance)成员变...原创 2017-04-14 11:56:40 · 647 阅读 · 2 评论 -
lua的元表
接触lua一年多,是要把lua的高级特性总结一下了.先说说元表吧.元表是什么?为什么要有元表?学过C++的童鞋应该知道操作符重载.例如,自定义一个复数类,可以让他的两个实例相加减等等.同理,lua的元表也可以让两个表相加减,但是他使用了更简单的语法.lua的元表是为了扩展lua的特性,使他的功能更加丰富.要想使一个表拥有加法操作的功能,必须给他添加一种元表__add,语法如下:...原创 2018-04-17 21:23:38 · 571 阅读 · 0 评论 -
skynet加载配置文件
看了skynet加载配置的地方,竟然发现好多知识点,记录下.skynet的配置文件是通过命令行传入到进程的,这个比较明了. 仔细读了一下这块代码,发现有不少细节,而且,有些lua函数竟然很少用过,下面就这块代码分析一下.intmain(int argc, char *argv[]) { const char * config_file = NULL ; if (argc > ...原创 2018-05-22 17:17:39 · 2603 阅读 · 0 评论 -
lua 热更新原理(二)
在讲lua热更新原理第二部分之前,先介绍一下lua调试相关的函数。调试函数能够帮助我们在开发中获取函数堆栈相关上下文信息,甚至改变函数的变量。getinfo ([thread,] f [, what]):返回关于一个函数信息的表。 你可以直接提供该函数, 也可以用一个数字 f 表示该函数。 数字 f 表示运行在指定线程的调用栈对应层次上的函数: 0 层表示当前函数(getinfo 自身); 1 层...原创 2018-06-11 18:28:27 · 3595 阅读 · 0 评论 -
lua 元表的补充说明
1 __index前面讲过lua元表的作用(详见lua元表),尤其对__index有重点讲解。在研究skynet源码时发现了__index新的用法,记录一下。我们已经知道__index的作用是表查找不到字段时的索引,索引我们见到的__index都是另一个表,实际上__index也可以是一个函数。函数在字段查找不到时触发。例如下面的代码:local function fun(t,...原创 2018-06-04 20:56:22 · 557 阅读 · 0 评论 -
lua面向对象生成实例的正确方式
写lua这么久了,也知道怎么样用lua来实现所谓的面向对象。下面这段代码是我常用来new一个新实例对象的:local Object = {a = 123}function Object:new (data) local data = data or {} setmetatable(data, {__index = self}) return data ...原创 2019-03-06 22:39:21 · 1127 阅读 · 0 评论