Lua Power Patches

lua-users home
wiki

Power patch 是一种对源代码分发版进行的小型补丁,它能实现一些有用的更改。Power patches 的评判标准在于修改的代码行数、通用性和向后兼容性。通过限制为局部修改,多个补丁协同工作的可能性很高。随着源代码包新版本的发布,这也能将维护工作降到最低。真正优秀的补丁生命周期很短,因为原始程序的作者会将其集成到他们的代码中。

欢迎提交新的 power patches、现有补丁移植到不同 Lua 版本以及 bug 修复。

如果您应用了一个修改 Lua 语法或语义的补丁,产生的语言不应称为“Lua”。

请参阅 LuaPowerPatchesArchive 获取旧版本 Lua 的补丁。如果一个补丁存在多个 Lua 版本(包括当前版本),它将显示在此页面。

如何应用补丁

将正确的 Lua 发行版解压到一个干净的目录。cd 到该目录的顶层并运行

patch -p1 < patchfile

补丁工具

Solaris 自带的版本)不支持统一 diff 格式(每行开头有 + 和 - 的)。GNU patch 支持。

补丁指南

cd lua
make clean
cd ../lua_new
make clean
cd ..
diff -urN lua lua_new > mychange.patch

补丁编写者参考

通常,Lua 内部文档很难找到——并且当前版本的此类文档更是稀少 [4]。以下是一些可能有帮助的资源


Lua 5.4 补丁

支持用户定义数据与 Lua 原生类型进行相等比较 (5.4.4)

此补丁添加了一个新的元方法 `__eqval`,当 '==' 或 '~=' 运算符的两个操作数中只有一个是表或用户数据时调用。标准的元方法 `__eq` 仅在两个操作数都是表或用户数据类型时调用。

目的是允许基于表或用户数据的高层数据类型直接与 Lua 原生类型进行比较。例如

local a = ...             -- table representing a numerical value, eg mpi or bint
if a == 2 then ...        -- the __eqval metamethod in a's metatable will be called

保存/恢复 readline 历史记录 (5.4.6)

将历史记录保存/恢复到文件(由 LUA_HISTORY 环境变量指定)。

高级 readline 支持 (5.4, 5.3, 5.2, 5.1, 5.0)

此补丁为 Lua 5.x 中现有的 readline 支持增加了以下功能:

应用补丁后,启动 Lua 并尝试以下操作(用 TAB 键替换 ~):

~~
fu~foo() ret~fa~end<CR>
io~~~s~~~o~~~w~"foo\n")<CR>

已验证适用于 Lua 5.0, 5.0.2, 5.1, 5.2, 5.3, 5.4.3。兼容的 readline 库包括 GNU readline 2.2.1, 4.0, 4.3, 5.0, 5.1, 6.0, 6.2, 7.0, 8.0;Mac OS X libedit 2.11;或 NetBSD libedit 2.6.5, 2.6.9。请注意,尽管版本号不同,5.3 补丁适用于所有 5.3.x 版本。

添加分发友好的默认模块路径 (5.4.6, 5.3.5, 5.2.0, 5.1.5)

此补丁在 /usr 下添加了默认模块路径,以及默认的 /usr/local,并考虑到 Debian 的多架构方案,使 Lua 能够找到作为系统一部分安装的库(例如,由 GNU/Linux 发行版安装的库)。

在 POSIX 系统上解释器中的更好的信号处理 (5.4.2, 5.3.5, 5.2.3, 5.1.5)

使用 sigaction 而不是 signal 以获得一致的行为,例如,按下 Ctrl-C 总是会退出阻塞在 I/O 上的 Lua 脚本(否则,这种行为取决于系统)。

复合赋值运算符

SvenOlsen 广受欢迎的复合赋值运算符补丁进行更新,允许类似 “object.counter += 2” 的语句。除了 5.4 (beta) 兼容性外,它还为先前实现的 +=、-=、*= 和 /= 添加了移位和按位运算符(<<=, >>=, &=, |=, 和 ^=)。++ 增量运算符未包含在内,因为它暗示了一个匹配的 --,而 -- 已用于注释。(而且 “+= 1” 只多了两个字符。)此外,不支持对元组进行复合赋值,因为(IMO)这会很容易写出非常混乱的 Lua 代码,而收益甚微。

我刚发现的一个奇怪的 bug:它在 REPL 中不起作用

> a = 1
> a += 2
3
> a
1

但在编译后的代码中有效。 :shrug

添加 'defer' 语句支持 (5.4.0)

此补丁为 Lua 5.4 添加了对 'defer' 语句的支持。'defer' 语句引入了一个匿名闭包,该闭包将在当前作用域退出时执行,无论是正常退出还是异常退出。

Example

  function test()
     defer print 'hello on exit' end
     error('error')
  end
  test()
上面的代码将打印 “hello on exit”。

请注意,Lua 5.4 的一个特性是延迟的闭包可能会被调用多次,因此它应该被编写成幂等的。

简写 lambda 函数 (5.4.2)

一种编写更简洁的匿名函数的语法糖,在将参数传递给高阶函数时非常有用。完全向后兼容,仅修改解析器,生成与函数语法相同的字节码。

结构 |arglist| expressionfunction(arglist) return expression end 的简写。

Lua 5.3 补丁

添加 'defer' 语句支持 (5.3.5)

此补丁为 Lua 5.3 添加了对 'defer' 语句的支持。'defer' 语句引入了一个匿名闭包,该闭包将在当前作用域退出时执行,无论是正常退出还是异常退出。

Example

  function test()
     defer print 'hello on exit' end
     error('error')
  end
  test()
上面的代码将打印 “hello on exit”。

为重复变量声明添加编译器警告/错误 (5.3.5, 5.2.4, 5.1.5)

此补丁为重复变量声明添加了编译器警告/错误,对于嵌套作用域中同名变量是警告,对于同一作用域中同名变量是错误。

示例:lua src.lua -> src.lua:12: warning Name [a] already declared will be shadowed。

示例:lua src.lua -> src.lua:12: Name [b] already declared near '='。

使用自定义全局名称预加载库 (5.3.4)

示例:lua -l json=rapidjson 在全局名称 json 下加载 rapidjson 模块。

无浮点数选项 (5.3)

此补丁增加了移除浮点数支持的选项。类似于下面的“Go Long Lua!”。

自迭代对象 (5.3.1)

为表提供一个默认迭代方法,功能上等同于 pairs(但不支持 __pairs 元方法)。

for k, v in {1,2,3} do print(k, v) end

还为表和用户数据提供了一个元方法 __iter

t = {"one", "two", "three"}; setmetatable(t, {__iter = ipairs}); for k, v in t do print(k, v) end

继续支持标准形式

for k, v in next, t, nil do print(k, v) end

通常写成

for k, v in pairs(t) do print(k, v) end

除了如果只提供一个 in 值,它必须是一个真正的函数(或闭包),而不是一个带有 __call 元方法的表或用户数据。

要编译此补丁,必须定义符号 ‘JH_LUA_ITER’。

为表构造器设置语法快捷方式 (5.3.1)

这是我之前为 Lua 5.2 编写的补丁的扩展和改进,旨在为指定集合(表中的集合成员是键,值始终为布尔 true)提供更简单的语法。补丁同时修改了源代码和 manual.html 中的文档。

该补丁允许在构造器字段中的名称前加上可选的点号。

t = {.cat = true, .dog = true} --> t = {cat = true, dog = true} 

这反映了使用名称键访问表的语法,并且可以与任何值一起使用,但其主要目的是允许

t = {.cat, .dog} --> t = {cat = true, dog = true} 

与之前的版本一样,也实现了以下快捷方式:

t = {[cat], [dog]} --> t = {[cat] = true, [dog] = true} 

这里的 'cat' 和 'dog' 都是表达式,所以下面的代码将创建与上面相同的集合:

t = {["cat"], ["dog"]} 

要编译此补丁,必须定义符号 ‘JH_LUA_SETINIT’。

整数指数运算 (5.3)

此补丁为 '^' 运算符实现了整数指数运算 (ipow),当两个操作数都是整数时。对于非负指数,使用平方求幂计算幂。根据“ipow 模式”处理负指数。有关更多信息,请参见 lvm.h。

此更改将对依赖 '^' 为整数给出浮点结果的代码造成一些问题。不过,通过明确使用数字类型(在需要浮点数的地方使用 '.0')可以轻松解决此问题。

提供了一个更新版本,没有不同的模式(指数为负时报错)。

Lua 5.2 补丁

表和用户数据的类型元表 (5.2.1)

Lua 支持表和用户数据类型的每个对象元表,以及其他每个类型的类型元表。对于表类型,存在一些类型元表的使用场景(对用户数据类型则较少)。例如,我们可以像字符串库那样,将表库函数公开为表对象的成员。

此补丁利用了 Lua 状态中所有类型都已存在类型元表指针的便利事实。当创建表或用户数据时,补丁会将类型元表指针复制到新对象中。这意味着对象会自动使用任何类型元表,直到并除非通过常规方式显式设置其元表来覆盖它。类型元表可以通过从 C 或 Lua(“getmetatable”)创建的新对象访问,并且可以用于从替换它的对象元表中进行委托。

我们需要一种方法来设置类型元表,使其与对象元表区分开。这仅从 C API 和 Debug 库中支持,这与现有的类型元表一致。我一直觉得不得不提供一个“dummy”对象给 ‘lua_setmetatable’ 来指定类型很不方便。我添加了 API 函数 ‘lua_settypemt’,它接受一个类型常量并为任何类型设置类型元表。一如既往,‘lua_setmetatable’ 用于设置表和用户数据对象的对象元表。它被弃用作为设置类型元表的方式,但对于除表和用户数据以外的类型,它在该角色中继续工作。从 Debug 库来看,例如使用

debug.settypemt("table", {__add=table.insert})

定义符号 'JH_LUA_TYPEMETA' 来编译补丁。

可以选择也定义符号 'JH_LUA_TABLECLASS' 来为表类型安装一个类型元表,该元表以方法形式公开表库。

二进制数字字面量 (5.2)

此补丁增加了二进制字面量。由于底层代码的重大更改,它的实现方式与我的 5.1 补丁不同。这次我没有支持八进制,因为它现在很少使用(尽管可以按照此补丁的相同模式轻松添加)。我还添加了 Java/Perl 风格的嵌入式下划线支持,因为它使格式化长二进制字符串更容易(由下面的 RobHoelz 建议,尽管此补丁仅在二进制字面量中启用下划线)。

有效的二进制字面量:0b1101;0B100100;0b1001_1111_0000_1010;0b11______01

下划线字符仅用于提高可读性,会被忽略。可以嵌入任意数量的下划线,但在第一个和最后一个二进制数字之间以及之后必须至少有一个二进制数字。

要编译此补丁,必须定义符号 'JH_LUA_BINCONST'。

C/C++ 风格注释

允许在 Lua 源代码中使用 C 风格(/*...*/)和 C++ 风格(//...)的注释。可以通过修改 llex.h 或 luaconf.h 中的 #defines 来启用其中一种或两种样式。标准的 Lua 注释仍然可用。

函数字段

允许在表中为函数字段使用特殊语法,以便

tbl = {}
function tbl:my_method(x, y) end
或者
tbl = { my_method = function(self, x, y) end }
可以写成
tbl = { function my_method(x, y) end }
也就是说,用这种语法声明的函数会获得方法的自动“self”参数。

1 月 19 日:修复了破坏匿名函数声明的 bug,例如 t = { function(args) end }

自迭代对象 (5.2, 5.1.4)

更新:收到印度尼西亚的 Sam Lie 的一个想法后,我扩展了这个补丁,将 pairs 设置为表的最后备选默认迭代器。补丁已重新命名以反映这个扩展范围。

此补丁为元表添加了一个新事件 __iter。如果将其包含在元表中,其值必须是一个签名与 pairsipairs 相同的函数。它为对象提供了一个默认迭代器,简化了泛型 for 语句。如果没有这样的元方法,则使用 pairs 迭代器(仅适用于表)。

t = {[3]="three",[2]="two",[1]="one"}
for k,v in t do print(k,v) end        -- uses pairs
setmetatable(t, {["__iter"]=ipairs})
for k,v in t do print(k,v) end        -- uses ipairs
for k,v in pairs(t) do print(k,v) end -- uses pairs (per standard Lua)
当然,可以使用自定义函数或闭包来代替 pairsipairs。对于列表,可以使用闭包来避免示例中需要键变量。

我提出这个作为 __pairs__ipairs 事件的替代方案,这些事件已在 Lua 5.2 中实现。我仍然认为这种方法更好,并继续将其作为补丁提供。这两种方法可以共存,实际上您可以为同一个对象指定所有三个元方法,这样 pairsipairs 都可以使用自定义行为,并且其中一个还可以指定为默认迭代器。

该补丁修改了 Lua 虚拟机,以测试 TFORLOOP 字节码指令的第一个参数的类型。如果它是函数,则使用原始代码。如果不是函数,则尝试引用其 __iter 元方法。如果这没有得到一个函数,并且正在迭代的对象是表,则尝试引用全局 pairs 函数。如果通过这两种方法之一获得了函数,则调用该函数,其三个返回值将覆盖 TFORLOOP 的原始三个参数。然后使用原始代码处理带有函数提供的迭代参数的泛型 for。请注意,这引入了标准 Lua 处理的一个细微变化:在第一次迭代期间而不是之前检测第一个参数不是函数的情况,并且它是一个函数类型的测试而不是可调用性的测试。这将破坏一些微妙的代码技巧,例如使用 __call 事件来“伪造”自迭代。

要编译此补丁,必须定义符号 ‘JH_LUA_ITER’。

表构造器的语法快捷方式 (5.2, 5.1.4)

此补丁为构造集合类表添加了一种新的语法快捷方式。如果字段的值缺失,则默认为布尔值 true,因此例如 {["saturday"], ["sunday"]} 构造的表与 {["saturday"] = true, ["sunday"] = true} 相同。

要编译此补丁,必须定义符号 ‘JH_LUA_SETINIT’。

按名称解包表 (5.2, 5.1, 5.0.2)

对赋值语句的增强,允许使用 in 关键字从表中解包命名值。(参见 lua-l 消息“patch: local a,b from t” [5]。)

    local a, b, c in some_table_expression
是语法的糖,等同于
    local t = some_table_expression
    local a, b, c = t.a, t.b, t.c

复合赋值运算符 (5.2)

一个允许 C 风格复合赋值的补丁;即,类似“object.counter+=2”的语句。支持的运算符有 +,-,..,/, 和 *。语法的详细信息请参见我的个人页面(参见:SvenOlsen)。对于相同问题的另一种(且兼容 5.1)方法,请参见 [6]

安全表导航 (5.2)

这里讨论的安全导航语义的语法补丁 [7]——一个索引操作 't?.v',它会抑制访问未定义表的错误。虽然对此类补丁似乎有广泛的兴趣,但关于如何最好地处理细节的意见不一。我下面发布了一个简单、轻量级的版本;我的个人页面(SvenOlsen)包含一个功能更强大的版本的代码和文档。

Lua 5.1 补丁

按 Lua 版本顺序排列,最新的在前,最旧的在后。

使 os.exit 关闭 lua_State (5.1.5)

如果提供可选的第二个参数为 true,则在退出前调用 lua_close,以便运行 finalizers。Lua 解释器在正常退出时已调用 lua_close,但其他嵌入 Lua 的应用程序可能不会;并且在使用 os.exit 时您可能希望此行为(强制非零退出状态)。

此行为无法通过库提供,只能通过修补 Lua 源代码并重新构建来提供。

使表遵守 __len (5.1.5)

此补丁使 #tbl 遵守 tbl 上的 __len 元方法,如 Lua 5.2 中所示。它还提供了一个新的全局函数 rawlen。

二次哈希 (5.1.5)

此补丁增强了 Lua 5.1 对抗 Hash DoS 攻击的能力。更多详情请参见 HashDos

打印 NUL 字符 (5.1.5)

通过使用 fwrite 而不是 fputs,使 print 打印 NUL 字符。有人通过修补 luaconf.h 让用户提供 luai_puts 宏来对其进行清理。

Autotoolized Lua (5.1.5)

此补丁使 Lua 发行版自启动,即使用 autoconf, automake 和 libtool 构建。适用于 Lua 5.1.5。

在打补丁之前必须解压文件

bunzip2 lua-X.Y.Z-autotoolize-rW.patch.bz2

注意:此补丁在多个地方错误地引用了版本 5.1.3,您可能需要修复它。

接下来,应用补丁。

打完补丁后,您需要为某些文件添加可执行权限。

chmod u+x autogen.sh config.guess config.sub configure depcomp install-sh missing

现在您可以运行 ./configure 了。

紧急垃圾收集器 (5.1.5)

此补丁在 EmergencyGarbageCollector 中进行了描述。

可 yield 的 for 循环 (5.1.5)

修改代码生成器,以便 for ... in 循环中的迭代器可以调用 yield。详细信息和测试代码可在 YieldableForLoops 获取。

请注意,当前版本的补丁会按照操作码的顺序排列,以在定义 LUA_COMPAT_TFORLOOP 时保持与编译后的 Lua 脚本的二进制兼容性。这会增加一些 VM 指令,以及相当多的补丁复杂性,否则补丁将只有大约 25 行。

string.format %s 补丁使用 __tostring (5.1.5)

更改 string.format %s,使其对非字符串 %s 参数应用 __tostring。

自定义错误对象支持 (5.1.5)

此补丁增强了 Lua 对自定义错误对象的支持。更改:

实例(因为它将被修改)。与其采用这种方案,不如理想的解决方案是由 Lua 核心管理与错误对象分开的位置。

有关更多信息,请参阅“Lua 中的异常模式” [3]

像算术运算符一样的相等运算符 (5.1.5)

这修改了相等运算符函数行为,使其能够处理不同类型的取值。例如,在标准 Lua 中,如果左操作数是用户数据而右操作数是数字,则相等测试会失败。此补丁会使用用户数据的 __eq 元方法(如果可用)。但请注意,Lua 不支持此功能的一个原因是 __eq、__lt 和 __le 元方法也用于 ~=、> 和 >=,通过反转操作数。因此,如果左操作数和右操作数都有元方法,您可能会惊讶于哪个被选中。目前,左元方法被优先使用。但当然,这对于 ~=、> 和 >= 测试是正确的方法!一个好的解决方案可能是添加 __ne、__gt 和 __ge 元方法。然后相等运算符将真正表现得像算术运算符一样。

八进制和二进制数字常量 (5.1.4)

这个简单的补丁添加了八进制和二进制常量。它们将在源代码字面量或通过 tonumber 隐式或显式转换的字符串内容中被识别。二进制常量形式为 0b10101。八进制常量形式为 0o176。为了与十六进制格式保持一致,也支持大写基数说明符,但出于明显的原因,不建议用于八进制!

要编译此补丁,必须定义符号 'JH_LUA_BINOCTAL'。

对 TValue 使用 NaN 打包 (5.1.4)

在 x86 上对 TValue 使用 NaN 打包以减少内存使用并获得微小的性能提升(与 LuaJIT 2 相同)。

它与标准 Lua 库完全兼容 ABI。

在一个测试脚本上,内存消耗从 28Mb 减少到 21Mb,性能提高了约 3.5-5%。

使用逗号语法进行多维数组索引 (5.1.4)

修改了解析器以支持使用逗号语法的多维数组索引,即 m[1,2] 被解析器视为等同于 m[1][2],从而允许像下面的代码

   -- test multi-dimensional arrays with comma syntax. also test
   -- constructors and multiple assignment to show they're not broken.
   m = {[1]={}, [2]="foo"}
   m[1,2] = "bar"
   print(m[2], m[1][2], m[1,2])  --> foo  bar bar
   m.foo = {}
   m.foo.bar = "baz"
   print(m["foo","bar"])         --> baz

虚拟机保持不变。

回溯中的 C 函数名 (5.1.4)

目前仅限于 GNU/Linux,此补丁将在从共享库加载的 C 函数的调试信息已编译时,将这些 C 函数的名称添加到回溯中。

允许数字中使用下划线 (5.1.4)

Perl 的一个优点是可以使用下划线来分隔大数字,所以而不是这样做:

local num = 1000000000000

你可以这样做:

local num = 1_000_000_000_000

按位运算符、整数除法和 != (5.1.4)

通过在 luaconf.h 中取消定义 LUA_BITWISE_OPERATORS,可以禁用所有这些功能。

位运算符首先将 lua_Number 转换为 lua_Integer,然后将结果转换回 lua_Number。

移除自动字符串<->数字转换 (5.1.4)

防止在算术和连接中进行字符串与数字之间的自动转换。这很有用,因为它能防止 bug;当自动转换是合理的(例如在 print 函数中)时,仍然可以通过调用相关的转换函数来完成。

当前版本并未严格移除库中所有不期望的类型转换;我更倾向于正确性而不是完整性。

为 LUA_INIT、LUA_PATH 和 LUA_CPATH 使用默认值 (5.1.4)

为独立解释器添加了一个 -t 开关,该开关使用上述变量的默认值,使得更易于以可控的方式运行 Lua。

无 varargs (5.1.4)

varargs 可能是多余的复杂性。此补丁将其移除。

解释器退出标志 (5.1.3)

[Sim Ops Studios],我们通过启动一个内核支持的线程来嵌入 Lua,该线程使用 C API 调用 Lua 脚本。在这种配置下,脚本可能会无限期挂起,导致无法在不强制终止线程的情况下干净地退出。此脚本提供了一种替代方案:“退出”状态标志,以及两个命令(luaL_getbailout 和 luaL_setbailout)来管理该标志。当该标志为真时,每个操作码都被解释为返回操作,强制 Lua 解释器无条件返回到顶层。然后 C 代码可以检查标志的状态,并在退出标志为真时干净地退出线程。使用此标志使得无法编写一个可以无中断运行的脚本(尽管脚本可能在意外的地方被终止)。

检查未定义的全局变量 (5.1.3)

此补丁在 DetectingUndefinedVariables 中进行了描述。

continue 语句 (5.1.3)

在解析器中添加了一个“continue”语句。虚拟机未改变。附带一个小型的测试套件。

与其修补 Lua,不如考虑 luaSub,它包含一个用于此目的的语法修改。

表作用域补丁 (5.1.3)

允许表构造函数封闭一个作用域,以便在表中使用的变量具有特殊含义。请参阅 TableScope

LNUM - 数字模式补丁(“整数补丁”)(5.1.3)

允许 Lua 内置数字是以下任何组合:LNUM_DOUBLE / LNUM_FLOAT / LNUM_LDOUBLE (long double) LNUM_INT32 / LNUM_INT64 LNUM_COMPLEX

用途:在内部使用 32 位或 64 位整数精度来处理所有 Lua 数字。在非 FPU 平台上,Lua 的性能会得到显著提升(40-500%)。对应用程序(脚本)级别以及现有的 Lua/C API 完全透明。

最新 svn(带测试套件)

svn export svn://slugak.dyndns.org/public/2008/LuaPatches/LNUM2

最新发布:[LuaForge LNUM 文件]

仍然欢迎来自应用程序的真实世界测试和性能数据。补丁基本“就绪”;除了 LDOUBLE 模式外,没有已知 bug;如果您发现任何问题,请分享您的经验。

该补丁可以优雅地离开整数范围,当结果不适合整数时,会自动转换为浮点数精度。

对于性能结果,有一个电子表格和易于使用的“make-plain/float/double/ldouble/complex”目标,可以在您自己的系统上运行。

整数 ASCII 值 (5.1.2)

又一个词法分析器的语法膨胀
print(#'a',#'\n')
97      10

请注意,这可能也能通过令牌过滤器实现,但对于 ASCII 值处理(base64、模糊协议解析)很有用。我只是想要比 if c>=b2a("A") and c<=b2a("Z") 更具表达力的方式。当时在 Lua 中没有办法将 ASCII 值作为常量获取。

此语法已经有一个含义(字符串长度),因为字符串可以放在单引号内。--lhf

模块执行提案 (5.1.2)

提供了一个新的命令行开关(-p),该开关通过 `package.loaded` 中的搜索器加载具有给定包名称的函数,然后将该函数作为脚本执行,并将命令行参数传递给该函数。补丁和描述在 ModuleExecutionProposal 中。

简洁的匿名函数 (5.1.2)

一些用于编写更简洁匿名函数的语法糖,在将参数传递给高阶函数时非常有用。完全向后兼容,并且只修改了解析器,发出与旧语法相同的字节码。有关详细信息,请参阅 [Readme]

简写 lambda (5.1.4)

一种编写更简洁的匿名函数的语法糖,在将参数传递给高阶函数时非常有用。完全向后兼容,仅修改解析器,生成与函数语法相同的字节码。

结构 |arglist| expressionfunction(arglist) return expression end 的简写。

扩展表构造语法以允许多返回值函数的多个展开 (5.1.1)

正如在邮件列表中多次讨论过的,并在 Aranha 中实现的那样,这是一个修改表构造语法以允许分号(;)展开前面列表项的补丁。

使用此补丁,` {foo(); bar()} ` 创建一个表,其中包含 `foo` 的所有返回值,后跟 `bar` 的所有返回值,而 ` {foo(), bar()} ` 仍然具有与当前 Lua 相同的语义。更精确地说,如果一个列表项后跟一个逗号,则截断为一个返回值;否则,它表示所有返回值(可能为零)。因此,` {foo(),} ` 会截断,但 ` {foo();} ` 和 ` {foo()} ` 不会。

该补丁还使字段定义的顺序精确地从左到右,这与当前 Lua 实现不同,在当前实现中,` {[3] = "foo", 1, 2, 3} ` 具有未定义的行为。这可能会导致定义方式如此的非常大的表的性能问题。

t = {
  "a", a = 1,
  "b", b = 2,
  "c", c = 3,
  -- etc
}

除此之外,性能影响很小;有时会快一点,有时会慢一点,但差别不大。我个人更喜欢精确的排序保证,但补丁可以轻松修改以更接近当前语义。请联系我获取更多详细信息。

实现很简单。当遇到分号时,编译器会生成代码来追加当前的表达式列表,并将最后一个表达式保留为多返回值。为了做到这一点,有必要将当前表的数组插入点保存在堆栈上,而不是将其硬编码到 VM 代码中,因此创建新表的 opcode 被修改为使用两个堆栈槽,将表放在第一个槽中,并将第二个槽初始化为 1。将数组值添加到表的 opcode 使用第二个堆栈槽作为起始索引,并将其更新为下一个起始索引。尽管这使用了一个额外的堆栈槽,但速度与现有代码大致相同。

让 luac 合并的文件访问参数 (5.1.1)

当 `luac` 将多个文件合并成一个字节码块时,生成的块不接受任何参数。这个小的补丁将 `...` 传递给合并块中的所有文件。

__usedindex 元方法 (5.1.1)

__usedindex 的行为与 __newindex 完全相同,但当被索引的键实际存在时(值被覆盖)。这允许简单地实现只读表、镜像 C 结构等,而无需缓慢/冗长/脆弱的表代理构造。已知与 LuaJIT 存在 bug,欢迎修复。

类似 PHP 的 'break N' 来跨越多重循环 (5.1.1)

允许语法如下: while foo do while bar do if baz then eek() break 2 end end end

如果 "foo and bar and baz" 条件成立,'break 2' 会立即跳出循环。该数字被计入可中断的范围(因此,“if”、“do”等不被计数)。

枚举/位运算补丁 (5.1.1)

添加了用于处理无符号 32 位位域的 C API 函数(toenum、isenum 等)。这些枚举值具有重载的 []、() 操作符,用于在 Lua 端执行位运算。枚举被分组到“家族”中,以防止意外使用错误的位掩码。

实现使用负的“tt”(Lua 类型)值作为枚举,并且它们是不可垃圾回收的(= 应该很快)。`type()` 函数返回两个值:“enum”和家族名称。缺少文档。

svn cat svn://slugak.dyndns.org/public/lua-bitwise/lua-5.1.1-enum-patch.diff
svn cat svn://slugak.dyndns.org/public/lua-bitwise/test.lua
svn cat svn://slugak.dyndns.org/public/lua-bitwise/README

Go Long Lua! (5.1)

此补丁通过将 Lua 数字的类型从 double 改为 long,消除了 Lua 5.1 使用的浮点运算。它实现了除法和模运算,使得 x == (x / y) * y + x % y。指数函数对于负指数返回零。该补丁移除了 difftime 函数,并且不应使用 math 模块。string.format 函数不再处理浮点指令 %e、%E、%f、%g 和 %G。通过移除 src/luaconf.h 中 LUA_NUMBER_INTEGRAL 的定义,可以获得基于 double 的 Lua 数字实现。

CNUMBER 补丁 (5.1)

提供了一种更有效的机制,用于从 Lua 访问数字 C 变量。

千字节/兆字节数字后缀 (5.1)

为数字添加 'K' 和 'M' 后缀(例如 150K 或 12M);二进制(K=2^10)而不是度量(K=10^3)。

在某些领域将 Lua 用作配置语言时很有用(在我们的情况下,是一个构建过程)。

Do 补丁 (5.1 beta)

将 "= do ... end" 转换为 "= function() ... end" 的语法糖(对于简单的回调函数很方便)。

svn cat svn://slugak.dyndns.org/public/lua-patches/do.patch
svn cat svn://slugak.dyndns.org/public/lua-patches/do.txt

与其修补 Lua,不如考虑 luaSub,它包含一个用于此目的的语法修改。

字面量(十六进制、UTF-8)(5.1 beta)

允许字符串中的 \x00..\xFFFF(十六进制)和 \u0000..\uFFFF(UTF-8 编码)字符。

svn cat svn://slugak.dyndns.org/public/lua-patches/literals.patch
svn cat svn://slugak.dyndns.org/public/lua-patches/literals.txt

变异运算符 (5.1-work6)

此补丁向 Lua 添加了变异运算符。具体来说,可以通过将 `__mutate_asn` 元方法附加到 Lua 对象来使用 `:=` 运算符进行值赋值(或您希望执行的任何其他操作)。添加其他变异运算符(如 += 或 `<<` 等)也很简单。

使用 debug.getinfo 检索函数元数 (5.1.5)

有时了解函数期望多少个参数很有用。此补丁允许您为 debug.getinfo(或 lua_getinfo)指定 'a',它将函数的元数放在名为 'arity' 的字段中。


RecentChanges · preferences
编辑 · 历史
上次编辑于 2024 年 1 月 1 日下午 1:40 GMT (差异)