将翻译成Lua时实现后置/前置递增/递减
我正在编写一个将LSL翻译成Lua的程序,但在实现递增和递减运算符时遇到了各种各样的问题。 LSL使用通常的类C语法(x ++,x-,++ x, - x)实现这些功能,但Lua不包含这些运算符。为避免大量的打字,我称这些运算符为“crements”。在下面的代码中,我将使用“...”来代表表达式的其他部分。
... x += 1 ...
不起作用,因为Lua只有简单的赋值。
... x = x + 1 ...
不起作用,因为这是一个语句,而Lua不支持在表达式中使用语句。LSL可以在表达式中使用crements。
function preIncrement(x) x = x + 1; return x; end
... preIncrement(x) ...
虽然它在表达式中提供了正确的值,但是Lua对于数字是传值的,因此原来的变量不会改变。如果我可以使它实际上改变变量,那么就都好了。更改环境可能不是一个好主意,我不知道x的范围是什么。我想我会接下来调查一下这个。翻译器可以输出范围细节。
假设上述函数存在-
... x = preIncrement(x) ...
由于它是一个语句,所以不适用。
其他解决方案开始变得非常混乱。
x = preIncrement(x)
... x ...
很好用,除非原始的LSL代码是这样的-
while (doOneThing(x++))
{
doOtherThing(x);
}
这会变成一大堆问题。在函数中使用表 -
function preIncrement(x) x[1] = x[1] + 1; return x[1]; end
temp = {x}
... preincrement(temp) ...
x = temp[1]
变得更加混乱,而且有相同的问题。
看起来我可能不得不分析周围的代码,而不仅仅是进行简单的翻译,以找出实现任何给定crement的正确方法。有没有简单的想法?
原文链接 https://stackoverflow.com/questions/9124751
你提出的解决方案只能在你的 Lua 变量全部都是全局变量的情况下才能够生效。除非 LSL 也采用了这种方法,否则将会遇到在不同位置使用同名变量的 LSL 程序转换为 Lua 程序时出现的问题。
Lua 只能修改一个 lvalue。传递给函数的表是这个规则的唯一例外。你可以使用一个本地化的表来存储所有的局部变量,在预增量和后增量方面可以有所帮助;它们可以在包含它们的表达式被求值之前求值。但是后增量需要在之后进行求值,这在 Lua 中是不可能的,至少不是不需要涉及到使用匿名函数的丑陋代码。
因此你只有一种选择:你必须接受某些 LSL 语句会转换成多个 Lua 语句的事实。
假设你有一个具有增量的 LSL 语句,就像这样:
f(integer x) {
integer y = x + x++;
return (y + ++y)
}
你可以将其转换为一个 Lua 语句,就像这样:
function f(x) {
local post_incremented_x = x + 1 -- 步骤 1,为后增量语句多写一个语句
local y = x + post_incremented_x
x = post_incremented_x -- 步骤 2,为后增量语句多写一个语句
local pre_incremented_y = y + 1
return y + pre_incremented_y
y = pre_incremented_y -- 这一行永远不会被执行
}
因此,基本上你将需要为每个增量和减量语句添加两个表述。对于复杂结构,这意味着需要计算表达式求值的顺序。
就我个人而言,我喜欢在语言中单独使用后减量和先减量的语句。但是当它们也可以用作表达式时,我认为这是语言的缺陷。它的语法糖很快就会成为语义上的糖尿病。
我认为要真正正确地完成这个任务,你需要进行更详细的分析,并将一些表达式拆分为多个语句,尽管许多表达式可能可以直接翻译。
请注意,至少在 C 语言中,可以延迟后增量/减量到下一个“序列点”,并将前增量/减量放在前一个序列点之前;序列点只出现在几个地方:在语句之间,在“短路运算符”(&&
和||
)中等等。(点击这里了解更多信息)
因此,将 x = *y++ + z * f();
替换为 { x = *y + z * f(); y = y + 1; }
是可以的,因为用户不能假设 y
将在语句中的任何其他内容之前被增加,只有在增加之前使用的值 *y
将是增加前的 y
。同样,可以使用 { y = y - 1; x = *y + z * f (); }
替换 x = *--y + z * f()
。
经过一番研究和思考,我想到了一个可能可行的方法。
对于全局变量 –
function preIncrement(x)
_G[x] = _G[x] + 1
return _G[x]
end
... preIncrement("x") ...
对于局部变量和函数参数(也是局部变量),在解析 crement 时我知道它是局部变量,我可以存储四个标志来告诉我正在使用哪些四个 crement 变量的 AST 结构。然后,当定义变量的时候,我可以输出像这样的内容 –
local x;
function preIncrement_x() x = x + 1; return x; end
function postDecrement_x() local y = x; x = x - 1; return y; end
... preIncrement_x() ...
大多数时候你在对代码的配置性进行评估。你会尝试将一种数据类型从一个传递到另一个中去,并称其为“翻译器”。而在这一过程中,你错过了正则表达式和其他模式匹配能力。这些能力在 LUA 中比 LSL 更丰富。而且由于 LSL 代码被传递到 LUA 中去了,尝试使用它们以及其他函数。这将更好地定义工作,并将其视为翻译器,而不是一个硬编码。
是的,我知道这是一段时间前就提出的问题了。但是,对于这个主题的其他观众来说,永远不要忘记你所在的环境。使用它们所提供的能力,最大化你的能力。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
Lua的设计基本上可以抵御这种实现。这可能是一个编译器/解释器问题,因为解释器可以知道变量仅在执行语句时才会改变。
在Lua中没有办法实现这种东西。在一般情况下不行。你可以通过将字符串传递给增量函数来为全局变量执行此操作。但显然它不能用于局部变量,或者在其自身是全局变量的表中的变量。
Lua不希望你这样做;最好在限制内找到工作方式。这意味着代码分析。