一步步写lua解释器--多参赋值的问题

有个问题倒是缠绕了很多时间,问题非常简单清晰,就是,函数的返回值取值个数的问题。例如

function ft() return 13, 78 end
local a, b, c = 3, 4, ft()
print(a, b,c)

a, b, c = 3, ft(), 5
print(a, b,c)

a, b, c = ft(), 5
print(a, b,c)

a, b, c = ft()
print(a, b,c)

以上需要ft函数返回值的个数不尽相同。看起来很简单,实际却难处理,而且不得不处理。因为函数在执行完毕时,必须要平衡堆栈。函数返回值的实现是往栈上压入数据,有几个返回值就压入几个。如果调用者没有需要那么多返回值,则导致栈的平衡被破坏。

其实需要多少个函数返回值,规则也很简单:在赋值的时候遇到函数,如果函数不是最后一个表达式,则只返回一个值(如果返回有多个值,则其余值省略,如果函数没有返回值,则压入一个Nil值),如果是最后一个表达式,则压入的个数是,变量的总个数 - 前面已经赋值的变量个数。

根据函数的返回值,和调用者需要的返回值,就可以正确的操作栈了:多余的pop,缺少的就压入Nil值。

赋值,运算的时候还是比较好处理,但是有函数调用函数时就比较麻烦了,例如:f1(f2())。由于解析这个表达式的时候,是先执行f2,根本不知道f1需要多个参数。还未执行到f1时当然也可以用其他的方法来获取其参数个数,但是太不优雅。一度卡在这里几个小时。

后来决定,当函数有像这样需要未知个数的返回参数时,则在函数退出时不清理堆栈,也就是假设f1需要f2的全部返回值。函数入参的操作其实就是变量初始化操作,也就是形参初始化为实参。函数形参个数在生成函数的时候就确定了,而实参个数也在调用时就可以知道。实际这两个参数就相当于赋值时变量的个数和值得个数,根据这两个数据就可以确定栈的平衡了。

此外,在像print需要不定参数,或f(...)需要全部全部参数时,也需要这样做。实现不定参数的函数,也只能把栈上的数据全部出栈,作为函数参数,不然想不到其他方法了。还有基于寄存器的虚拟机没有使用栈,不知道是如何处理的,这个到时候研究研究。

 

您有好的思路或有问题可以在下面留言,或者加入QQ群 858791125 讨论。

项目地址:
https://github.com/shonm520/mlua

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值