# 语言理论演进计划（law / 抽象层 / 类型驱动错误）

状态：Active  
作者：Chen + Copilot（整理稿）  
日期：2026-02-17

> 注（2026-02-18）：`laws` 相关实现已从运行时与宏中回退，当前文档仅作为未来迭代指导，不代表已上线能力。

---

## 1. 目标

基于当前 Calcit 工程现实，**逐步**推进到更“理论可解释”的语言形态，重点覆盖：

1. trait 体系补齐“法则层”（laws）与默认验证机制。
2. 把抽象层从 runtime 规则堆叠，收敛为“核心语义 + 推导扩展”。
3. 将错误报告升级为“类型驱动开发”导向（给出下一步重构建议）。

非目标：

- 不在单个版本内做破坏性重写。
- 不先追求完整 Haskell 化（高阶类型系统/纯粹 effect 全量引入）。
- 不牺牲当前可运行与可迁移性。

---

## 2. 当前问题快照

### 2.1 trait 缺少 law 层

现状：`deftrait`/`defimpl`/`impl-traits` 提供了接口与实现绑定，但缺少“应满足的代数法则”声明与验证。

影响：

- 同一 trait 的不同实现行为可能不可替换。
- 文档约定无法自动校验，长期容易语义漂移。

### 2.2 抽象层偏实现导向

现状：不少能力以 runtime 规则累积推进，缺少“核心语义 -> 语法糖/能力层”的清晰分层。

影响：

- 新功能进入时容易引入特例。
- 语义一致性与可证明性不足。

### 2.3 错误报告仍偏“报错”

现状：已有 hint，但多数错误仍偏“指出失败点”，不够“指导下一步重构”。

影响：

- 学习与调试成本偏高。
- 类型系统价值不能完全转化为开发体验。

---

## 3. 总体演进策略

采用“三阶段、可回滚”的增量路线：

- **Phase A（最低风险）**：把规范写成机器可读元数据，先做到“可声明”。
- **Phase B（中风险）**：把声明接入检查器与测试框架，做到“可验证”。
- **Phase C（中高风险）**：把错误系统升级为“诊断 + 修复建议”，做到“可引导重构”。

每阶段都要求：

- 保持向后兼容（默认不破坏旧代码）。
- 提供 feature flag 或可配置开关。
- 提供对应 smoke tests。

### 3.1 保守试验约束（新增）

为避免解释器复杂度上升，所有试验默认遵循：

1. **解释器不增新分支**：不在 `evaluate_expr/call_expr` 增加语义特判。
2. **优先做推导层**：先在 preprocess、lint、测试框架、文档元数据落地。
3. **语法新增先“可降级”**：任何新声明都能被忽略或展开成现有语义。
4. **失败可回滚**：用 feature flag 控制，默认关闭或 warning 模式。

可接受改动层级（按优先顺序）：

- 第一层：文档规范、元数据结构、CI 检查。
- 第二层：preprocess 诊断、`cr` 子命令扩展。
- 第三层：runtime 文案增强（不改求值语义）。

不建议在早期做的事：

- 新运行时值类型。
- 新求值规则（尤其是调用/绑定语义）。
- 影响现有宏展开稳定性的语法硬切换。

---

## 4. 分阶段计划

## Phase A：law 声明与语义分层清单（2~4 周）

### A1. trait law 声明（仅声明，不强制）

新增可选语法（草案级）：

- 在 `deftrait` 中增加 `:laws` 区域，支持命名 law 与谓词模板。
- 支持 `:doc` / `:examples` 附带 law 说明。

示意：

- `Semigroup`: associativity
- `Monoid`: associativity + identity
- `Functor`: identity + composition

### A2. 核心语义分层文档化

建立一份“核心语义边界表”：

- Core（必须稳定）：值模型、调用语义、绑定规则、模式匹配核心。
- Derived（可演进）：语法糖、宏扩展、宿主能力包装。
- Host（平台相关）：FFI、IO、环境能力。

要求每个新增功能在 PR 中标注所属层级。

### A3. 错误码分类（不改文案结构）

先统一错误类别枚举映射：

- type-mismatch
- arity-mismatch
- trait-law-violation（预留）
- unresolved-symbol
- platform-capability

> 先做分类，不强推文案重写。

### Phase A DoD

1. 至少 2 个核心 trait 支持 `:laws` 声明（可空实现）。
2. 发布“语义分层清单”并接入开发文档。
3. 错误分类映射在 runtime/preprocess 输出链路可查询。

---

## Phase B：law 验证与抽象层约束落地（3~6 周）

### B1. law-check 框架

增加专用测试入口（例如 `check-laws`）：

- 对声明了 law 的 trait，运行样例驱动验证。
- 支持“最小样例集 + 可扩展随机样例（可选）”。

默认策略：

- CI 先 warning 模式。
- 稳定后可在特定 trait 升级为 fail-on-violation。

### B2. 抽象层准入规则

新增 lint/CI 规则：

- Core 层禁止直接依赖 Host 能力。
- Derived 层新增语法糖时必须给出 core 等价展开。
- Host 能力必须显式标注平台与稳定级别。

### B3. trait 冲突的结构化报告

对于方法名冲突，不只提示“有冲突”，还输出：

- 冲突来源 trait 列表。
- 当前选择路径（precedence）。
- 推荐解法（显式 trait-call / 重命名 / 调整 impl 顺序）。

### Phase B DoD

1. 至少 1 个 trait（例如 `Monoid` 或 `Functor`）有可执行 law-check。
2. CI 能检查核心分层违规。
3. 冲突诊断包含“来源 + 选择 + 修复路径”。

---

## Phase C：类型驱动错误与重构建议（4~8 周）

### C1. 诊断从“错误”升级为“问题卡片”

每条关键错误输出统一包含：

- What happened
- Why（类型/语义原因）
- Next 1~2 actions（可执行）
- 示例链接（如 `query examples`）

### C2. 常见模式自动修复建议

先覆盖高频场景：

- 参数个数错误 -> 建议签名/调用最小改法。
- trait 缺失 -> 建议 `assert-traits` / `impl-traits` 路径。
- 平台能力错误 -> 建议替代 API 或运行目标。

### C3. 类型驱动提示入口

给开发流程增加一条轻量入口：

- `cr doctor`（草案）或现有命令扩展，汇总当前文件“下一步可修复项”。

### Phase C DoD

1. 三类高频错误具备标准化重构建议。
2. 错误信息可稳定指向文档/示例。
3. 团队内部试用反馈中，“看报错后可直接行动”的比例显著提升。

---

## 5. 风险与缓解

- 风险：law 语法过早固化导致后续包袱。
  - 缓解：Phase A 仅声明，不强制；保留实验标记。

- 风险：验证框架引入 CI 波动。
  - 缓解：先 warning，再逐步提升到 fail。

- 风险：错误文案重写工作量大。
  - 缓解：优先高频 20% 场景，分批覆盖。

---

## 6. 推荐优先级（马上可做）

1. 先落地 Phase A（声明与分层）——最小改动、收益清晰。
2. 在 trait 体系选一个样板 trait 做 law-check 试点。
3. 把错误输出模板统一成“问题卡片”结构（先不做自动修复）。

### 6.1 三个“推导式优先”试点（可立即开始）

#### 试点 A：Law 只做元数据 + 测试映射

- 在 trait 文档/定义处声明 law 名称，不改变运行时行为。
- 由 `check-laws`（或测试脚本）把 law 名称映射到现有测试样例。
- 解释器零改动；收益是“语义约束可追踪”。

#### 试点 B：抽象分层只做 CI 准入

- 给模块或 PR 增加 `core/derived/host` 标签。
- 用静态规则检查“core 不可依赖 host”。
- 不改运行时；收益是“架构边界可持续维护”。

#### 试点 C：错误卡片先由 preprocess 生成

- 保留现有错误类型，仅在 preprocess 侧补 `Why/Next`。
- 对高频 3 类错误做模板化建议（arity、trait 缺失、平台能力）。
- 不改解释器求值；收益是“开发体验立即提升”。

#### 试点评估门槛（继续/停止）

- 两周内若满足以下至少两项，则继续推进：
  - 同类问题二次出现率下降。
  - 平均修复轮次下降。
  - PR review 在语义争议上的耗时下降。

- 若不满足，则回滚到“仅文档+检查”层，不进入 runtime。

---

## 7. 评估指标（建议）

- 语义一致性：同 trait 多实现的行为偏差问题数量。
- 可维护性：新增功能触发的特例分支数。
- 开发体验：错误到修复的平均迭代次数。
- 迁移成本：现有项目升级失败率与修复时长。

---

## 8. 结论

这条路线的核心不是“追求学术完整度”，而是把学术语言里最有价值的三个能力逐步工程化：

- **可声明的语义约束（laws）**
- **可解释的抽象分层（core/derived/host）**
- **可执行的错误引导（type-driven diagnostics）**

在不破坏现有生态的前提下，这能持续提升 Calcit 的理论一致性与工程可用性。

---

## 9. 直接执行清单（不拆 issue）

以下清单按“尽量不增加解释器复杂度”设计，优先修改文档、preprocess、测试和 CLI 提示层。

### 9.1 第 1 步：先把 law 变成可追踪元数据（仅声明）

目标：不改求值语义，只让 trait 能表达 law 信息，并可在文档/工具中读取。

建议改动：

- 在 trait 相关文档中增加 law 字段约定（先文档约束，再代码约束）。
- 在 `deftrait` 相关 preprocess 路径中允许读取 `:laws`（可选，不填不影响）。
- law 内容先支持简单命名：`associativity`、`identity`、`composition`。

验收标准：

- 不带 `:laws` 的旧代码保持行为一致。
- 带 `:laws` 的定义在 preprocess 阶段可被识别并保留元信息。

当前状态：

- 暂缓执行，代码侧未启用该能力。
- 继续保留为后续设计入口，待语义收益明确后再推进。

### 9.2 第 2 步：增加一个最小 law-check 入口（warning 模式）

目标：用现有测试体系验证 law，不引入新运行时规则。

建议改动：

- 增加一个命令入口（可在 `cr` 子命令或测试脚本中实现）用于执行 law-check。
- 先对 1 个 trait 做样板（建议 `Monoid` 或 `Semigroup`）。
- 输出为 warning，不阻断主流程。

验收标准：

- 能输出“哪个 law 失败 + 最小反例（若可得）”。
- 对没有 law 声明的 trait 不做额外检查。

### 9.3 第 3 步：错误卡片化（先做 3 类高频）

目标：保留原错误类型，增强诊断信息为“可执行下一步”。

先覆盖：

- arity 错误
- trait 缺失/方法冲突
- 平台能力不匹配（如 registered proc 平台限制）

统一模板：

- What happened
- Why
- Next actions（1~2 条）

验收标准：

- 现有错误 kind 不变（兼容上层逻辑）。
- 至少 3 类错误能稳定输出 Next actions。

### 9.4 第 4 步：分层准入只在 CI 做

目标：限制复杂度扩散，不在 runtime 加硬编码分层判断。

建议改动：

- 增加轻量规则：Core 不直接依赖 Host。
- Derived 功能需提供 core 等价展开说明（文档或注释）。

验收标准：

- 新增功能 PR 必须标注层级（core/derived/host）。
- 规则触发时给出明确修复建议，而不是仅失败。

### 9.5 建议执行顺序与命令

推荐顺序：`9.1 -> 9.2 -> 9.3 -> 9.4`。

每步完成后建议执行：

- `cargo test`
- `yarn check-all`

如果某步导致复杂度明显上升（新增解释器分支、语义特判），则回滚到上一步，仅保留文档/检查器侧改动。
