在转换为Lua时实现后/前增量/减量

在转换为Lua时实现后/前增量/减量,lua,pass-by-reference,lua-scripting-library,Lua,Pass By Reference,Lua Scripting Library,我正在编写一个LSL到Lua的翻译程序,在实现递增和递减运算符时遇到了各种各样的问题。LSL使用常见的C类语法(x++,x-,++x,--x)实现了这些功能,但Lua没有。为了避免大量的打字,我把这类操作符称为“crements”。在下面的代码中,我将使用“…”表示表达式的其他部分 ... x += 1 ... 行不通,因为Lua只有简单的任务 ... x = x + 1 ... 不起作用,因为这是一个语句,Lua不能在表达式中使用语句。LSL可以在表达式中使用crement functio

我正在编写一个LSL到Lua的翻译程序,在实现递增和递减运算符时遇到了各种各样的问题。LSL使用常见的C类语法(x++,x-,++x,--x)实现了这些功能,但Lua没有。为了避免大量的打字,我把这类操作符称为“crements”。在下面的代码中,我将使用“…”表示表达式的其他部分

... x += 1 ...
行不通,因为Lua只有简单的任务

... x = x + 1 ...
不起作用,因为这是一个语句,Lua不能在表达式中使用语句。LSL可以在表达式中使用crement

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);
}
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() ...
变成了一整罐虫子。在函数中使用表-

function preIncrement(x)  x[1] = x[1] + 1;  return x[1];  end
temp = {x}
... preincrement(temp) ...
x = temp[1]
甚至更混乱,也有同样的问题


看起来我可能需要实际分析周围的代码,而不是简单地进行翻译,以确定实现任何给定crement的正确方法。有人有什么简单的想法吗?

Lua被设计成几乎不受此类实现的影响。这可以作为一种编译器/解释器问题来完成,因为解释器可以知道变量只有在执行语句时才会改变

没有办法在Lua中实现这种事情。一般情况下不是这样。可以通过向增量函数传递字符串来为全局变量执行此操作。但显然,它不适用于局部变量,也不适用于本身是全局的表中的变量


Lua不想让你这么做;最好找到一种在限制范围内工作的方法。这意味着代码分析。

只有当您的Lua变量都是全局变量时,您提出的解决方案才会起作用。除非LSL也这样做,否则在不同地方翻译使用相同方式调用变量的LSL程序时会遇到麻烦

Lua只能对每个语句修改一个左值-传递给函数的表是该规则的唯一例外。您可以使用一个本地表来存储所有的本地数据,这将有助于您完成预;可以在计算它们所包含的表达式之前对其进行计算。但是后期必须进行评估,这在lua中是不可能的,至少在没有涉及匿名函数的丑陋代码的情况下是不可能的

所以您有一个选择:您必须接受一些LSL语句将被转换为几个Lua语句

假设您有一个增量如下的LSL语句:

f(integer x) {
  integer y = x + x++;
  return (y + ++y)
}
function f(x) {
  local post_incremented_x = x + 1 -- extra statement 1 for post increment
  local y = x + post_incremented_x
  x = post_incremented_x -- extra statement 2 for post increment

  local pre_incremented_y = y + 1
  return y + pre_incremented_y
  y = pre_incremented_y -- this line will never be executed
}
您可以将其转换为如下Lua语句:

f(integer x) {
  integer y = x + x++;
  return (y + ++y)
}
function f(x) {
  local post_incremented_x = x + 1 -- extra statement 1 for post increment
  local y = x + post_incremented_x
  x = post_incremented_x -- extra statement 2 for post increment

  local pre_incremented_y = y + 1
  return y + pre_incremented_y
  y = pre_incremented_y -- this line will never be executed
}
因此,对于语句中使用的每个..crement,您基本上必须添加两个语句。对于复杂结构,这意味着计算表达式的求值顺序


出于价值考虑,我喜欢将后减量和前减量作为语言中的单独语句。但我认为这是一种语言的缺陷,当它们也可以用作表达时。语法上的甜头很快就变成了语义糖尿病。

我认为要真正做到这一点,你必须做一些更详细的分析,并将一些表达式拆分为多个语句,尽管许多表达式可能可以直接翻译

请注意,至少在C中,您可以将后增量/减量延迟到下一个“序列点”,并将预增量/减量放在前一个序列点之前;序列点仅位于几个位置:语句之间、“短路运算符”(
&&
|
)等


因此,替换
x=*y+++z*f(){x=*y+z*f();y=y+1;}
-不允许用户假定
y
将在语句中的任何其他内容之前递增,只允许
*y
中使用的值在递增之前是
y
。类似地,
x=*--y+z*f()
可以替换为
{y=y-1;x=*y+z*f();}

经过一些研究和思考,我想出了一个可行的想法

全球的-

function preIncrement(x)
  _G[x] = _G[x] + 1
  return _G[x]
end
... preIncrement("x") ...
对于局部变量和函数参数(它们是局部变量),我在解析crement时知道它是局部的,我可以存储四个标志来告诉我变量AST结构中使用了四个crement中的哪一个。当需要输出变量定义时,我可以输出如下内容-

while (doOneThing(x++))
{
  doOtherThing(x);
}
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。尝试将它们与其他功能一起使用。这将更多地将工作定义为翻译,而不是硬通关


是的,我知道这是不久前问过的。不过,对于这个话题的其他观众来说。永远不要忘记你工作的环境。曾经尽你所能利用他们给你的一切。

\u G[“变量”]应该适用于全局变量。表中的变量不是问题,LSL没有这样的东西。这仍然留给当地人。在函数中定义的函数可以访问上层局部变量,这样可能会使事情变得更简单。嗯,你是指我建议的使用_G的解决方案吗?这只是解决方案的一半