Skip to content

— 运算符重载编程指南 ​

玄铁通过魔术方法(Magic Methods)支持运算符重载,使自定义类型可使用 +、== 等原生运算符。本文档覆盖完整 API、实现细节与实战示例。


快速开始 ​

xuantie
型 向量 {
    设 x
    设 y
    函 造(ax, ay) { 此.x = ax ; 此.y = ay }
    函 _加_(other) { 返 造 向量(此.x + other.x, 此.y + other.y) }
}

设 v1 = 造 向量(1, 2)
设 v2 = 造 向量(3, 4)
设 v3 = v1 + v2     // 自动调用 v1._加_(v2)
示("v3=(" & v3.x.转字() & "," & v3.y.转字() & ")")
// 输出: v3=(4,6)

魔术方法对照表 ​

运算符魔术方法参数返回值等效调用
+_加_(other)新实例a._加_(b)
-_减_(other)新实例a._减_(b)
*_乘_(other)新实例a._乘_(b)
/_除_(other)新实例a._除_(b)
%_模_(other)新实例a._模_(b)
==_等_(other)布尔(真/假)a._等_(b)
!=_等_(other)布尔(取反)非 a._等_(b)

== 与 != 的限定规则 ​

== 和 != 仅在至少一个操作数为自定义类型(变量类型含 型: 前缀)时启用重载。否则直接走内建 xt_eq(指针/值比较)。这意味着:

  • 弱引用 == 字符串 → 内建比较,不触发 _等_
  • 整型 == 整型 → 内建比较
  • 向量 == 向量 → 重载 _等_

算术重载详解 ​

单次加法 ​

xuantie
型 向量 {
    设 x, y
    函 造(ax, ay) { 此.x = ax ; 此.y = ay }
    函 _加_(other) { 返 造 向量(此.x + other.x, 此.y + other.y) }
}

设 v1 = 造 向量(1, 2)
设 v2 = 造 向量(3, 4)
设 v3 = v1 + v2

若 v3.x == 4 且 v3.y == 6 { 示("PASS: 单次加法正确") }

链式加法 ​

xuantie
设 total = 造 向量(0, 0)
设 k = 0
当 k < 20 {
    total = total + 造 向量(1, 1)
    k = k + 1
}
若 total.x == 20 且 total.y == 20 { 示("PASS: 链式加法正确") }

嵌套表达式 ​

xuantie
设 a = 造 向量(1, 0)
设 b = 造 向量(0, 1)
设 c = 造 向量(2, 3)
设 result = a + b + c     // 等价于 (a + b) + c

若 result.x == 3 且 result.y == 4 { 示("PASS: 嵌套表达式正确") }

比较重载详解 ​

== 重载 ​

xuantie
型 向量 {
    设 x, y
    函 造(ax, ay) { 此.x = ax ; 此.y = ay }
    函 _等_(other) {
        返 此.x == other.x 且 此.y == other.y
    }
}

设 v1 = 造 向量(5, 5)
设 v2 = 造 向量(5, 5)
若 v1 == v2 { 示("相等") } 否 { 示("不等") }

!= 重载 ​

!= 不需要单独定义——编译器自动对 _等_ 的结果取反:

xuantie
若 非 (v1 != v2) { 示("v1 和 v2 相等") }
// v1 != v2 → 调用 v1._等_(v2) → 取反 → 实现 != 语义

实现原理 ​

编译期分派 ​

编译器在遇到运算符时:

  1. 检查操作数类型是否为标量(raw_i64 / i1 / double)→ 标量直接生成 LLVM 原生指令(如 add i64)
  2. 非标量类型 → 查找魔术方法(如 _加_)→ 通过 xt_dict_get 动态分派
  3. == / != 特殊处理:仅当操作数含自定义类型(型: 前缀)时启用重载,否则走 xt_eq(内建指针/值比较)

运行时流程(以 v1 + v2 为例) ​

1. 检查 v1 是否为堆指针(bit 0 == 0)
2. 若是:xt_dict_get(v1, "_加_") 查找魔术方法
3. 找到 → 提取 XTFunction → 调用 func_ptr(v1, v2)
4. 未找到 → 回退到内建 LLVM 运算

== 的入口 alloca 提升 ​

== 的重载路径使用 alloca 作为 PHI 节点的替代方案(在 overload/fallback 两分支存储结果,merge 处加载)。为避免 LLVM 支配性错误,此 alloca 被提升到函数入口块。

此机制是本会话修复的核心内容——此前 inline alloca 在 若 条件块内导致"Instruction does not dominate all uses!"错误。


完整测试示例 ​

参见项目测试文件:Test/52_运算符重载链.xt

xuantie
型 向量 {
    设 x, y
    函 造(ax, ay) { 此.x = ax ; 此.y = ay }
    函 _加_(other) { 返 造 向量(此.x + other.x, 此.y + other.y) }
    函 _等_(other) { 返 此.x == other.x 且 此.y == other.y }
    函 转字() { 返 "向量(" & 此.x.转字() & "," & 此.y.转字() & ")" }
}

设 v1 = 造 向量(1, 2)
设 v2 = 造 向量(3, 4)
设 v3 = v1 + v2
示("v1+v2=" & v3.转字())                    // 向量(4,6)

设 v4 = 造 向量(5, 5)
设 v5 = 造 向量(5, 5)
若 v4 == v5 { 示("v4 等于 v5") }            // 由 _等_ 判断
若 v4 != v5 { 示("不等") } 否 { 示("相等") } // _等_ 结果取反

已知限制 ​

  • == 重载仅限自定义类型:弱引用、Result、Socket 等运行时类型不触发 _等_,直接走内建 xt_eq(指针比较)。如需值语义比较,需手动调用方法。
  • 链式 == 不推荐:a == b == c 会先计算 a == b(返回布尔),再与 c 比较。布尔与自定义类型的 == 走内建路径。

基于 VitePress 静态构建 · 文档内容与仓库 GUIDE/ 同源

玄铁玄铁 XUANTIE · 中文系统级编程语言MARK 玄·折 120×120 · STROKE 8 · NO CURVES