Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 49 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ FakeLua 是一个可嵌入的 Lua 子集编译引擎:将 Lua 脚本编译为 C

编译器对函数的数学参数自动做类型推断与特化:

1. **TypeInferencer** 对每个顶层函数运行迭代不动点推断(leave-one-out),识别出真正参与算术运算的参数(math params)。
2. **CGen** 为每个含数学参数的函数生成 `2^k` 个特化版本(`int64_t` / `double` 组合),以及一个运行时入口分发器,根据实际参数类型路由到对应特化体。
3. 特化体内的算术运算直接用原生 C 类型(`int64_t`/`double`)计算,比较表达式也生成原生 C `bool` 而非走 `CVar` 装箱路径,彻底消除热路径上的类型判断开销。
1. [TypeInferencer](file:///home/project/fakelua/src/compile/type_inferencer.h) 对每个顶层函数运行迭代不动点推断(leave-one-out),识别出真正参与算术运算的参数(math params)。
2. [CGen](file:///home/project/fakelua/src/compile/c_gen.h) 为每个含数学参数的函数生成 `2^k` 个特化版本(`int64_t` / `double` 组合),以及一个运行时入口分发器,根据实际参数类型路由到对应特化体。
3. 特化体内的算术运算直接用原生 C 类型(`int64_t`/`double`)计算,比较表达式也生成原生 C `bool` 而非走 [CVar](file:///home/project/fakelua/include/fakelua.h#L198) 装箱路径,彻底消除热路径上的类型判断开销。

以递归 Fibonacci(n=32)为例,GCC 后端比 Lua 5.4 快 **43.7x**,TCC 后端快 **10.4x**(详见 [benchmark/README.md](benchmark/README.md))。

Expand All @@ -33,23 +33,31 @@ FakeLua 是一个可嵌入的 Lua 子集编译引擎:将 Lua 脚本编译为 C
- 生成高效的类型化 C 代码,消除动态类型装箱开销
- 支持根据调用上下文自动生成 int64/double 专特化版本

### CVar:ABI 安全的跨边界值类型
### [CVar](file:///home/project/fakelua/include/fakelua.h#L198):ABI 安全的跨边界值类型

```cpp
struct CVar {
int type_;
int flag_;
union { bool b; int64_t i; double f; VarString *s; VarTable *t; } data_;
int type_ = 0;
int flag_ = 0;
union cvar_data {
bool b;
int64_t i;
double f;
VarString *s;
VarTable *t;
VarMulti *m;
};
cvar_data data_{};
};
static_assert(std::is_standard_layout_v<CVar>);
static_assert(std::is_trivially_copyable_v<CVar>);
```

`CVar` 是 JIT 代码与 C++ 宿主之间传递值的唯一载体,强制为标准布局(POD),保证 arm64 等平台的 ABI 兼容性。
[CVar](file:///home/project/fakelua/include/fakelua.h#L198) 是 JIT 代码与 C++ 宿主之间传递值的唯一载体,强制为标准布局(POD),保证 arm64 等平台的 ABI 兼容性。

### VarInterface:可扩展的复杂类型桥接
### [VarInterface](file:///home/project/fakelua/include/fakelua.h#L17):可扩展的复杂类型桥接

`VarInterface` 是 Lua table 等复杂类型与宿主之间的抽象接口,宿主可按需实现自己的版本接入原有对象系统。库内附带 `SimpleVarImpl` 开箱即用。
[VarInterface](file:///home/project/fakelua/include/fakelua.h#L17) 是 Lua table 等复杂类型与宿主之间的抽象接口,宿主可按需实现自己的版本接入原有对象系统。库内附带 [SimpleVarImpl](file:///home/project/fakelua/include/fakelua.h#L61) 开箱即用。

### 多返回值与参数展开(Multi-Return & Parameter Expansion)

Expand Down Expand Up @@ -81,7 +89,7 @@ static_assert(std::is_trivially_copyable_v<CVar>);
- 类型推导基于静态分析,复杂的动态类型操作无法优化
- 函数 specialization 基于调用点的 math 参数发现
- 函数参数上限 32 个(通过常量 `kMaxFunctionInputParams` 统一配置)
- 数学特化参数上限 8 个(通过常量 `kMaxMathSpecializedParams` 统一配置,超过此限制的数学参数不进行特化,作为普通动态参数处理)
- 数学特化参数上限 8 个(通过常量 [kMaxMathSpecializedParams](file:///home/project/fakelua/include/fakelua.h#L14) 统一配置,超过此限制的数学参数不进行特化,作为普通动态参数处理)

## 快速上手

Expand Down Expand Up @@ -138,6 +146,7 @@ ctest --test-dir build -V
- `--entry`:入口函数名(默认 `main`)
- `--jit_type`:`0`=TCC,`1`=GCC
- `--repeat`:重复调用次数(用于性能测量)
- `--debug`:是否启用调试模式(默认 `false`,若为 `true` 则输出生成的 C 源码)

### C++ 嵌入示例

Expand All @@ -156,7 +165,7 @@ int main() {
}
```

`Call()` 支持最多 32 个参数,参数与返回值在原生 C++ 类型与 `CVar` 之间自动转换。
[Call()](file:///home/project/fakelua/include/fakelua.h#L318) 支持最多 32 个参数(受到 [kMaxFunctionInputParams](file:///home/project/fakelua/include/fakelua.h#L13) 的统一限制),参数与返回值在原生 C++ 类型与 [CVar](file:///home/project/fakelua/include/fakelua.h#L198) 之间自动转换。

## 性能基准

Expand All @@ -178,12 +187,12 @@ int main() {

```cpp
// 手动管理(不推荐,容易泄漏)
State* s = FakeluaNewState(StateConfig{});
State* s = [FakeluaNewState](file:///home/project/fakelua/include/fakelua.h#L262)([StateConfig](file:///home/project/fakelua/include/fakelua.h#L252){});
// ... 使用 s ...
FakeluaDeleteState(s);
[FakeluaDeleteState](file:///home/project/fakelua/include/fakelua.h#L265)(s);

// 或使用 RAII 风格(推荐)
FakeluaStateGuard guard(StateConfig{});
[FakeluaStateGuard](file:///home/project/fakelua/include/fakelua.h#L268) guard([StateConfig](file:///home/project/fakelua/include/fakelua.h#L252){});
State* s = guard.GetState();
// ... 使用 s ...
// 自动释放
Expand All @@ -193,18 +202,18 @@ State* s = guard.GetState();

| 函数 | 功能 |
|------|------|
| `FakeluaNewState()` | 创建 FakeLua 状态 |
| `FakeluaDeleteState()` | 释放 FakeLua 状态 |
| `CompileFile()` | 编译 Lua 文件 |
| `CompileString()` | 编译 Lua 代码字符串 |
| `Call()` | 调用编译后的函数 |
| `GetLastRecordedCCode()` | 获取最近编译的 C 代码 |
| `SetVarInterfaceNewFunc()` | 设置自定义 VarInterface 工厂 |
| `SetDebugLogLevel()` | 设置全局调试日志级别 |
| [`FakeluaNewState()`](file:///home/project/fakelua/include/fakelua.h#L262) | 创建 FakeLua 状态 |
| [`FakeluaDeleteState()`](file:///home/project/fakelua/include/fakelua.h#L265) | 释放 FakeLua 状态 |
| [`CompileFile()`](file:///home/project/fakelua/include/fakelua.h#L308) | 编译 Lua 文件 |
| [`CompileString()`](file:///home/project/fakelua/include/fakelua.h#L311) | 编译 Lua 代码字符串 |
| [`Call()`](file:///home/project/fakelua/include/fakelua.h#L318) | 调用编译后的函数 |
| [`GetLastRecordedCCode()`](file:///home/project/fakelua/include/fakelua.h#L315) | 获取最近编译的 C 代码 |
| [`SetVarInterfaceNewFunc()`](file:///home/project/fakelua/include/fakelua.h#L322) | 设置自定义 VarInterface 工厂 |
| [`SetDebugLogLevel()`](file:///home/project/fakelua/include/fakelua.h#L329) | 设置全局调试日志级别 |

### 类型转换

FakeLua 提供 `inter::NativeToFakelua()` 和 `FakeluaToNative()` 自动推导型转换:
FakeLua 提供 [`inter::NativeToFakelua()`](file:///home/project/fakelua/include/fakelua.h#L355)[`FakeluaToNative()`](file:///home/project/fakelua/include/fakelua.h#L458) 自动推导型转换:

```cpp
// 原生 → FakeLua
Expand All @@ -219,7 +228,7 @@ std::string native_str = inter::FakeluaToNative<std::string>(v_str);

### Table 与对象互转

通过实现 `VarInterface` 可实现 Lua table 与原生对象的双向映射:
通过实现 [`VarInterface`](file:///home/project/fakelua/include/fakelua.h#L17) 可实现 Lua table 与原生对象的双向映射:

```cpp
class CustomVar : public VarInterface {
Expand All @@ -245,6 +254,8 @@ Lua 源码
[预处理] → normalized AST (preprocessor)
[语义分析] → analysis result (semantic_analysis)
[类型推导] → type hints (type_inferencer)
[C 代码生成] → C 源码 (c_gen)
Expand All @@ -258,15 +269,16 @@ Lua 源码

| 模块 | 职责 |
|------|------|
| `lexer/parser` | Lua 词法和语法解析 |
| `syntax_tree` | AST 表示和遍历 |
| `preprocessor` | Lua 语法规范化(如 functiondef 提升) |
| `type_inferencer` | 静态类型推导和 specialization 决策 |
| `c_gen` | C 代码生成和类型驱动优化 |
| `compile_common` | 公共类型推导和代码生成工具 |
| `jit/*` | TCC 和 GCC 后端集成 |
| `state` | FakeLua 运行时状态管理 |
| `var` | 动态值 CVar 和转换工具 |
| [`lexer/parser`](file:///home/project/fakelua/src/compile/bison/) | Lua 词法和语法解析 |
| [`syntax_tree`](file:///home/project/fakelua/src/compile/syntax_tree.h) | AST 表示和遍历 |
| [`preprocessor`](file:///home/project/fakelua/src/compile/preprocessor.h) | Lua 语法规范化(如 functiondef 提升) |
| [`semantic_analysis`](file:///home/project/fakelua/src/compile/semantic_analysis.h) | 语义和控制流分析(如未定义符号分析等) |
| [`type_inferencer`](file:///home/project/fakelua/src/compile/type_inferencer.h) | 静态类型推导和 specialization 决策 |
| [`c_gen`](file:///home/project/fakelua/src/compile/c_gen.h) | C 代码生成和类型驱动优化 |
| [`compile_common`](file:///home/project/fakelua/src/compile/compile_common.h) | 公共类型推导和代码生成工具 |
| [`jit/*`](file:///home/project/fakelua/src/jit/) | TCC 和 GCC 后端集成 |
| [`state`](file:///home/project/fakelua/src/state/) | FakeLua 运行时状态管理 |
| [`var`](file:///home/project/fakelua/src/var/) | 动态值 CVar 和转换工具 |

## 项目结构

Expand Down Expand Up @@ -298,7 +310,7 @@ fakelua/
## 常见问题

### Q: 为什么选择 Lua 子集而不是完整 Lua?
A: 完整 Lua 的动态特性(如 metatable、varargs、多返回值)很难高效编译。子集实现聚焦于可静态分析的常见模式,通过类型推导和 JIT 编译获得接近 C 的性能。
A: 完整 Lua 的某些动态特性(如 metatable、varargs)很难高效编译。子集实现聚焦于可静态分析的常见模式,通过类型推导和 JIT 编译获得接近 C 的性能。目前也支持了受限的多返回值和参数展开,但更复杂的元表(metatable)或协程等特性尚不支持

### Q: TCC 和 GCC 后端如何选择?
A: **TCC** 快速编译(适合脚本小、编译频繁);**GCC** 优化充分(适合脚本大、运行次数多)。在同一 API 下可根据场景动态选择。
Expand All @@ -307,7 +319,7 @@ A: **TCC** 快速编译(适合脚本小、编译频繁);**GCC** 优化充
A: 可以,TCC 后端体积小,编译速度快,适合嵌入式。核心库依赖极少(仅 C++ 标准库),可交叉编译。

### Q: 如何调试生成的 C 代码?
A: 启用 `CompileConfig::debug_mode`,查看日志和 C 代码;使用 `GetLastRecordedCCode()` 导出 C 代码进行分析。
A: 启用 [`CompileConfig::debug_mode`](file:///home/project/fakelua/include/fakelua.h#L232),查看日志和 C 代码;使用 [`GetLastRecordedCCode()`](file:///home/project/fakelua/include/fakelua.h#L315) 导出 C 代码进行分析。

### Q: 支持多线程吗?
A: 每个 `State` 当前为线程本地对象,多线程环境中应为每个线程创建独立的 `State`。
A: 每个 [`State`](file:///home/project/fakelua/include/fakelua.h#L259) 当前为线程本地对象,多线程环境中应为每个线程创建独立的 [`State`](file:///home/project/fakelua/include/fakelua.h#L259)
Loading