unluac 1.2.1

Multi-dialect Lua decompiler written in Rust.
Documentation
# Parser

> **职责**:把某个 dialect 的字节流解析成保真的 raw 模型,一次性固化后层恢复会依赖的所有协议事实。
>
> **不负责**:lowering 语义、CFG 切块、任何推断。
>
> **例子**`bytes(lua54)``parse_lua54_chunk``RawChunk{ header, protos: [RawProto{...}] }`

## 入口

```
src/parser/mod.rs
  parse_chunk(bytes, options)          -- 自动探测版本,按版本字节分派
  parse_lua51_chunk / ...lua55 / luajit / luau  -- 强制 dialect 入口
```

## 模块布局

```
src/parser/
  mod.rs           入口 + 版本分派
  raw.rs           统一 raw 模型 + accessor(后层消费这里,不直接碰 dialect 内部)
  reader.rs        BinaryReader:varint / endian / 字节级读取
  options.rs       ParseOptions(ParseMode / StringEncoding / StringDecodeMode)
  error.rs         ParseError
  dialect/
    opcodes.rs            define_opcode_enum! / define_opcode_kind_table! 宏
    puc_lua/
      header.rs           PUC-Lua chunk header 解析
      layout.rs           字段顺序布局
      instruction.rs      指令编解码
      proto.rs            proto 读取骨架
      sections.rs         debug section 驱动
      strings.rs          字符串读取
      macros.rs           define_puc_lua_opcodes! / define_puc_lua_instruction_codec!
    lua51/ ... lua55/     各版本:mod.rs / parser.rs / raw.rs / debug.rs
    luajit/               同上
    luau/                 同上
  debug.rs         dump_parser(委托到各 dialect debug.rs)
```

## 数据流

```
bytes
  └─ parse_chunk(或 parse_lua54_chunk 等)
       └─ Lua54Parser::parse(bytes)       -- dialect/lua54/parser.rs
            ├─ BinaryReader               -- reader.rs
            ├─ puc_lua::read_header       -- puc_lua/header.rs
            ├─ puc_lua::read_proto        -- puc_lua/proto.rs
            └─ RawChunk { header, main proto tree }
                  └─ RawProto { instrs, consts, upvalues, children, debug_info, extra }
```

## 应优先复用的共享设施

| 设施 | 用途 |
|---|---|
| `BinaryReader` | 所有字节级读取,含 `read_varint_u32_lua54` / `read_u32_le`|
| `define_puc_lua_opcodes!` | 声明 opcode enum + label table,避免手写大段 match |
| `define_puc_lua_instruction_codec!` | operand 编解码共享骨架 |
| `puc_lua/proto.rs` | PUC-Lua 家族 proto 读取骨架,lua52~55 不应各自复制 |
| `raw.rs` accessor | 后层消费协议事实的正式入口 |

## 维护规范

1. **协议事实必须在 parser/raw 收口**:来源于字节编码(而非运行语义)的事实必须在此固化。  
   - 典型:`EXTRAARG` 与前一条指令的绑定、Luau closure const 到 child proto slot 映射、Lua 5.5 字符串复用展开。  
   - 边界:`local <const>` 不是 parser 能从 chunk 读出的——只有 `local <close>` 依赖运行时语义线索。
2. **parser.rs 只负责按协议顺序读取**:opcode label 大表、operand decode 大表应放到 opcode 宏或共享设施。
3. **raw.rs 只保存稳定事实**:只有后层实际消费的 typed extra 和 accessor,不保存单次读取的临时中间态。
4. **dialect debug.rs 只展示本 dialect 产物**:不做跨 dialect 判断,不重新校验 parser 已保证的版本约束。
5. **错误在 parser 边界暴露**:协议不合法优先报 `ParseError`,不拖到 transformer 再暴露。

## 向后提供的事实

`RawChunk` / `ChunkHeader` / `RawProto` / `RawInstr` / `RawConstPool` / `RawUpvalueInfo` / `RawDebugInfo` / `RawString` / 各 dialect raw extra。

## 排错指引

| 症状 | 检查点 |
|---|---|
| 指令数量 / 常量数量解析错误 | `puc_lua/sections.rs` 长度字段读取 |
| opcode 识别失败 | `dialect/opcodes.rs` 宏展开是否漏了某个 opcode |
| extra-word 绑定错位 | `parser.rs` EXTRAARG 绑定逻辑 |
| raw accessor 返回 None | `raw.rs` extra 类型是否与 dialect 版本匹配 |
| 想看 raw 结构 | `unluac --dialect lua54 --debug --target-stage parse <file>` |