From 137ceed2966fc4472ae40617f084256c05e3a4bf Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Tue, 25 Aug 2026 13:02:48 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20Lua=204.0=20?= =?UTF-8?q?=E7=A7=BB=E6=A4=8D=E8=AF=84=E4=BC=B0=20+=20compat=5F40.h=20?= =?UTF-8?q?=E9=AA=A8=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 明确支持范围: doString/runScript(单次)/loadFunction/callFunction/IO重定向/typed - 明确不可实现: 管道模式与 load_lib 压栈(4.0 无 luaL_loadfile) - 关键 API 映射表(lua_call 即保护调用/lua_ref 替代 Registry/ pushboolean→pushnumber/_ERRORMESSAGE 全局取错误) - compat_40.h 骨架: 版本宏 LUA_VERSION_NUM=400 与 LUA_OK 定义 --- doc/ADAPTATION-lua40.md | 64 +++++++++++++++++++++++++---------------- lib/lua/compat_40.h | 22 ++++++++++++++ 2 files changed, 61 insertions(+), 25 deletions(-) create mode 100644 lib/lua/compat_40.h diff --git a/doc/ADAPTATION-lua40.md b/doc/ADAPTATION-lua40.md index 86a56ca..a8b799d 100644 --- a/doc/ADAPTATION-lua40.md +++ b/doc/ADAPTATION-lua40.md @@ -1,38 +1,52 @@ # Lua 4.0 分支移植评估(ADAPTATION.md) > 本分支已 vendor Lua 4.0.1 官方源码到 `lib/lua/`。 -> **桥接层尚未适配**——Lua 4.0 的 C API 与 5.x 存在代际差异,需要按本文档改造后方可使用。 +> **桥接层尚未适配**——需要按本文档指引改造后方可有限使用。 -## 当前状态 +## 支持范围 -- ✅ Lua 4.0.1 源码就位 -- ❌ `lib/lua_runner.cpp` / `lib/lua_cj_api.cpp` 未适配(仍为 Lua 5.4 API) -- ❌ 仓颉层 `src/bridge.cj` 无需改动(FFI 签名与版本无关) +经过源码分析,Lua 4.0 可实现的有限支持: -## 移植要点 +| 功能 | 支持 | 说明 | +|------|------|------| +| `doString` | ✅ | `lua_dostring(L, s)` 直接映射 | +| `runScript`(单次) | ✅ | `lua_dofile` + `lua_call` 组合 | +| `loadFunction` | ✅ | 文件名→`lua_dofile`(返回函数)→`lua_ref` 锁定 | +| `callFunction` | ✅ | `lua_getref`→`lua_call` → `lua_settop` 取结果 | +| `unloadFunction` | ✅ | `lua_unref` | +| I/O 重定向 | ✅ | Registry 存 iopath(同 5.1/5.2 方案) | +| typed interop | ✅ | 全部映射为 number(无 boolean 类型) | +| **管道模式** | ❌ | 4.0 无 `luaL_loadfile`,无法分离编译与执行 | +| **`load_lib`** | ❌ | 同上,块压栈不可实现 | -Lua 4.0 是第一个引入 `lua_State*` 的版本,但 API 与 5.x 有以下关键差异: +## 关键 API 差异 -| 能力 | Lua 5.4(当前桥接实现) | Lua 4.0 | 改造方案 | -|---|---|---|---| -| 创建状态机 | `luaL_newstate()` + `luaL_openlibs()` | `lua_open(stacksize)` + `lua_baselibopen()` 等逐个打开 | 重写 init | -| 加载文件 | `luaL_loadfile()` + `lua_pcall()` 两步 | `lua_dofile(L, path)` 一步完成 | run() 重写;错误处理从 pcall 返回值改为 lua_dofile 返回码 | -| 执行字符串 | `luaL_dostring()` | `lua_dostring(L, s)` | 直接映射 | -| 调用栈顶函数 | `lua_pcall(L, nargs, MULTRET, 0)` | `lua_call(L, nargs, nresults)`(无保护,出错直接 abort) | 需包一层 `lua_cpcall` 或接受非保护语义 | -| 函数引用表 | `luaL_ref(L, LUA_REGISTRYINDEX)` | `lua_ref(L, lock)` / `lua_getref` / `lua_unref` | loadFunction/callFunction 全套改名 | -| 压栈 | `lua_pushinteger`(5.3+) / `lua_pushnumber` / `lua_pushboolean` | 仅 `lua_pushnumber` / `lua_pushstring`(无 integer 类型、boolean 用 number 0/1) | typed interop 退化为 number-only | -| 取值 | `lua_tointeger` / `lua_isinteger` | 无 | capture_result() 统一 CJT_NUM | -| 栈操作 | `lua_gettop` / `lua_settop` / `lua_remove` / `lua_pop` | 同名存在 ✅ | 兼容 | -| extraspace I/O 重定向 | `lua_getextraspace()` | **不存在** | 改 Registry 存储 iopath*(参照 lua_5.1.5/lua_5.2.4 分支方案) | -| print/io 劫持 | `lua_pushcfunction` + `lua_setglobal("print")` | `lua_register(L, name, func)` | 可映射 | +| 5.x 函数 | 4.0 等价 | 备注 | +|----------|----------|------| +| `luaL_newstate()` | `lua_open(stacksize)` | 4.0 需指定栈大小(如 `lua_open(1024)`) | +| `luaL_openlibs()` | 逐库 `lua_*libopen` | 逐个调用 `lua_baselibopen`/`lua_iolibopen`/... | +| `lua_pcall` | `lua_call` | 4.0 的 `lua_call` 是**保护调用**,返回 status | +| `luaL_loadfile` | **不存在** | 无法预编译;管道模式不可实现 | +| `luaL_dostring` | `lua_dostring(L, s)` | 直接映射 | +| 错误信息 | `_ERRORMESSAGE` 全局 | 非栈顶,需取全局函数输出 | +| `LUA_REGISTRYINDEX` | `lua_ref` / `lua_getref` | 4.0 引用表机制不同 | +| `lua_pushboolean` | `lua_pushnumber` | 4.0 无 boolean 类型 | +| `lua_pushcfunction` | `lua_pushcclosure(L, fn, 0)` | 0 个闭包上值 | +| `luaL_ref`/`luaL_unref` | `lua_ref`/`lua_unref` | 4.0 的 `lua_ref(L, 1)` 锁定并返回 ref | +| `luaL_newmetatable` | 无 | 需 `lua_newtable` + `lua_settagmethod` | +| `lua_pushlightuserdata` | `lua_pushusertag` | 需分配 tag | -## 预估工作量 +## 估算工作量 -- 桥接层 C++:~300 行改动(init/run/loadfunction/callfunction/I-O 重定向五大块) -- 测试:GTest 大部分可保留,PackagePathConfig 与 require 相关断言需按 4.0 语义重写 -- 构建系统:CMakeLists 文件集需按 4.0 源码列表调整(无 loadlib.c/loslib.c 等) +- 桥接层 C++ 重写:~400 行 +- 测试:GTest 中管道相关测试(`MultipleLoadUnload`、管道链)无法运行 +- 构建系统:CMakeLists 按 4.0 文件集重写(源码结构完全不同) +- 仓颉层:无需改动 ## 结论 -技术上可移植但性价比低:Lua 4.0 发布于 2000 年,语言本身无 integer 类型、 -无保护调用、GC 与现代版本差异大。建议仅在确有历史脚本兼容需求时投入。 +技术上可行但收益有限: +- 管道模式(项目核心特性)无法实现 +- 无 `luaL_loadfile` 导致 `load`/`runScript` 语义与 5.x 版本不同 +- 4.0 发布于 2000 年,实际使用场景极少 +- 建议仅在需要加载特定 Lua 4.0 遗留脚本时投入适配 diff --git a/lib/lua/compat_40.h b/lib/lua/compat_40.h new file mode 100644 index 0000000..6c3c844 --- /dev/null +++ b/lib/lua/compat_40.h @@ -0,0 +1,22 @@ +#ifndef COMPAT_40_H +#define COMPAT_40_H +/* Lua 4.0.x 兼容层。 + 支持范围: callFunction / doString / runScript(单脚本) / I/O 重定向。 + 不支持: 管道模式(4.0 无 load+call 分离 API, luaL_loadfile 是 5.0 新增)。 + + 关键差异与映射: + - lua_call(L,n,r) 在 4.0 即为保护调用(返回 status), 等价 5.x 的 lua_pcall + - 无 LUA_REGISTRYINDEX: 用 lua_ref(L,1) 锁定栈顶值, lua_getref 取回 + - 无 lua_pushboolean: boolean 用 number 0/1 表示(4.0 无 boolean 类型) + - 无 luaL_loadfile/loadbuffer: 无法分离编译与执行 → 管道不可实现 +*/ + +/* ---- 版本宏 ---- */ +#define LUA_VERSION_NUM 400 + +/* ---- 成功码 ---- */ +#ifndef LUA_OK +#define LUA_OK 0 +#endif + +#endif /* COMPAT_40_H */