Glyphs and operators#
Faber 在符号具有结构意义时使用字形。以下是词法分析器识别的源字形完整清单。
类型形状#
逻辑与位运算#
赋值更新#
可选链与非空断言#
字面量分隔符#
标点符号#
Latin vocabulary and structural glyphs#
三处信号选择,使 Faber 源码一眼可辨。
Faber 作出了三处刻意的信号选择,它们协同作用,生成具有稳定语法形态的源码。读者在了解代码将被编译到哪个目标后端之前,就能看出每个构造的语义角色。
三处信号#
这三者被设计为相互加强。在一个 locale 下熟悉 Faber 的读者,可以在任何 locale 下阅读它,因为字形和结构从不改变。熟悉 Rust 后端的读者仍然能识别 Faber 源码,因为拉丁语关键字和类型优先的顺序产生了一种独特的视觉调性。
类型优先声明#
Faber 在每个声明中把类型置于名称之前。这与主流的 C 语系语法相反,且是刻意为之:
类型优先声明意味着数据的形态是读者看到的第一件事。这自然契合那些从左到右按语义广度阅读的语言——中文、印地语和阿拉伯语的声明遵循同样的顺序。
函数 divide(整数 a, 整数 b) → 整数 ∪ 空类型 {
如果 b ≡ 0 则 返回 皆无
返回 a / b
}
拉丁语行为词汇#
Faber 为每个具有行为或语法形态的构造使用拉丁语词汇。该词汇小而规整,源自单一古典源头,而非大多数编程语言那种混合词源。
绑定与转移#
控制流#
拉丁语词汇是可绑定的——它随规范包一同发布,但可通过 reader locale 重新映射。泰国程序员看到的是 ถ้า 而不是 如果;中国程序员看到的是 函数 而不是 函数。该词汇并非特权;只有语法才是。
结构字形#
在行为词汇使用拉丁语单词之处,结构含义使用通用字形。这些字形绝不本地化,也绝不在不同渲染中改变含义。它们是使 Faber 源码可被识别的视觉锚点,无论关键字以哪种人类语言渲染。
类型形态#
比较与逻辑#
绑定约定至关重要#
有一个字形选择值得特别关注,因为它是新读者最容易混淆的点:
大多数语言对 = 进行重载,既用于"在类型中定义此字段",又用于"在此变量中放入运行时值"。Faber 拆分了这些工作。每个 ← 都是活跃的数据流;每个 Type { … } 内部的 = 都是 类 字段布局。
# Runtime binding: ← attaches a value to a name
常量 整数 count ← 0
变量 文本 label ← "ready"
count ← count + 1
# Structural shape: = defines field values inside a literal
常量 _ p ← Point {
x = 10,
y = 20
}
与主流语言对比#
下表展示了常见编程语言模式如何映射到 Faber 的三信号系统。Faber 一列为每个不同的语义任务使用不同的字形或关键字——没有重载。
参考资料#
- EBNF 语法——完整的字形与关键字清单
- examples/corpus/——包含 292 个示例文件的语言语料库,覆盖所有关键字
- examples/corpus/operatores/——运算符与字形示例
- 戒律——守护这些信号的九条设计法则
读者包片段#
函数 问候(文本 姓名) → 文本 {
若 姓名 ≡ "" 则 返回 "你好,世界"
返回 "你好," ⊕ 姓名
}
类型-first 声明:
数字 计数 ← 0
文本 名字 ← "费伯"
固定 圆周率 ← 3.14
可变 计数器 ← 0
当 计数器 < 10 {
计数器 ← 计数器 + 1
}
迭代 项 于 列表 {
若 项 > 100 则 返回 项
}
枚举 颜色 {
红色
绿色
蓝色
}
否则 情况 {
红 ⇒ 返回 "停止"
绿 ⇒ 返回 "通行"
}
## Canonical vs sugar surfaces
*多种可解析形式,一种语义形态。*
Faber 设计中的一个反复出现的模式:语言为每个构造定义**唯一的规范拼写**,但接受多个**糖式拼写**,它们在语义上完全等价。编译器不会偏好其中之一——两者都解析为同一个 AST 节点。格式化器根据上下文和模式决定输出哪种拼写。
> **规则:** 糖式拼写与长形式在语义上完全等价。
> 多种形式都解析为同一个 `HirAnnotation` 或类型节点。
> `faber format --canonical` 偏好规范拼写;作者模式则保留作者书写的糖式形式。
### 数值类型糖 {#numeric-type-sugar}
数值类型既有长形式的规范拼写,也有紧凑的糖式形式。选择以模块为单位,而非以代码库为单位——一个 CLI 包可以全部使用长形式,而一个张量内核模块使用糖式:
| 糖式 | 规范形式 | 领域 |
|-------|----------------|--------|
| `tf32`, `tf32[4]`, `ti64[2, 3]` | `tensor<f32, _>`, `tensor<f32, [4]>` | 稠密张量——`t` + 位宽 + 可选形状 |
| `sf32`, `sf32[2, 3]`, `si64[N]` | `sparsa<f32, _>`, `sparsa<f32, [2, 3]>` | 稀疏张量——`s` + 位宽 + 可选形状 |
| `mf32[4, 4]`, `mu32[3, 3]` | `matrix<f32, [4, 4]>` | 寄存器类矩阵——`m` + 位宽 + 形状 |
| `lf32`, `lu32`, `li64` | `lista<f32>`, `lista<u32>` | 列表——`l` + 位宽 |
**通用 Faber(偏好长形式):**
常量 列表<f32> values ← 空集
常量 tensor<f32, [2, 3]> grid ← 空集
常量 i32 narrow ← 7
**数值模块(偏好糖式):**
入口 {
常量 lf32 values ← 空集
常量 tf32[2, 3] grid ← 空集
常量 i32 narrow ← 7
}
糖式**仅适用于类型位置**。命名为 `f32`、`tf32` 或 `mf32` 的值标识符不受影响——编译器只有当它们出现在类型位置时,才将其解释为糖式。一个一致使用糖式的文件,应在文件顶部声明一次:
# STYLE: numeric sugar (tf32, mf32, sf32, lf32, lu32)
### 注解糖 {#annotation-sugar}
Faber 注解遵循与数值类型相同的双形式模型。注解是附加在声明上的编译器所拥有的元数据——例如 `@ 选项` 用于 CLI 选项定义,或 `@ 未来` 用于异步函数。
**规范形式:** 带有显式字段名的花括号记录:
@ 选项 {
binding = verbose,
简 = "v",
详 = "verbose",
类型 = 布尔,
全局 = 真,
描述 = "Enable verbose output"
}
**糖式形式:** 位置参数和命名别名:
@ 选项 verbose 简 "v" 详 "verbose" 类型 布尔 全局 描述 "Enable verbose output"
两种形式都生成相同的 `HirAnnotation` 记录。规范形式显式且自文档化;糖式形式简洁,适用于字段顺序已广为人知的常用注解。`faber format --canonical` 偏好花括号记录;作者模式则保留作者选择的形式。
### 作者模式与规范格式化 {#author-vs-canonical-formatting}
`faber format` 命令有两种模式,与"规范 vs 糖式"原则相对应:
| 模式 | 命令 | 输入 | 输出 |
|------|---------|-------|--------|
| 作者 | `faber format` | 已解析的 AST + 前导 trivia | 保留 `#` 注释、空行和糖式拼写的 Faber 源码 |
| 规范 | `faber format --canonical` | 已分析的 HIR + `TypeTable` | 归一化的 Faber——无注释、规范拼写、无糖式 |
两种模式都经过编译器的完整前端处理(词法分析、解析、分析——用于规范模式)。无效的源码会产生编译器诊断信息——格式化器不会悄悄地格式化有错误的输入。
两种模式的关键规则:
- 四空格缩进
- Stroustrup 风格花括号:左花括号 `{` 与控制头位于同一行
- 作者模式保留空行的*存在*,但会合并多于一个的连续空行
- 作者模式不会插入源码中原本不存在的空行
- 规范模式将类型拼写归一化为长形式,将张量糖式归一化为规范形式,将注解归一化为花括号记录
- 规范模式对可空联合输出 `T ∪ 空类型`,对可选参数输出 `可选`
### 设计原则 {#design-principle}
"规范 vs 糖式"模式在多处出现,因为它是一个有意的设计原则,而非一系列零散的便利措施:
| 领域 | 规范形式 | 糖式 |
|--------|-----------|-------|
| 张量类型 | `张量<f32, [4]>` | `tf32[4]` |
| 注解 | `@ 选项 { binding = verbose }` | `@ 选项 verbose ...` |
| 格式化 | `faber format --canonical` | `faber format`(作者模式) |
| 读者区域设置 | 拉丁语(`la`) | 任意区域设置包 |
该模式服务于两个目标。其一,降低入门门槛——新用户可以书写 `tf32[4]`,而无需键入 `张量<f32, [4]>`。其二,保持规范语言无歧义——当精度至关重要时,长形式表达的含义明确无误。格式化器在两者之间架起桥梁:作者书写糖式,审阅者可以请求规范形式,而 CI 可以强制执行任意一种。
### 参考资料 {#references}
1. `radix/docs/design/numeric-type-sugar.md`——完整的糖式家族、拼写偏好
2. `radix/docs/design/annotation-sugar.md`——双形式注解模型
3. `radix/docs/design/faber-canonical-surface.md`——作者模式与规范格式策略
4. `faber/docs/EBNF.md`——糖式形式的语法表