Glyphs and Latin
Glyphs and operators#
Faber 使用符號,其中符號本身具有結構意義。以下是詞法分析器所辨識的完整來源符號清單。
值流程#
| 符號 | 意義 |
|---|---|
← | 執行期繫結、重新指派與變更 |
→ | 函式回傳型別 |
⇥ | 替代退出 — 錯誤通道型別或內嵌轉換復原 |
∴ | 閉包連接符 — 將閉包體與其簽名相連((a, b) → T ∴ a + b) |
型別形狀#
| 符號 | 意義 |
|---|---|
∷ | 靜態型別標註(編譯期轉型) |
↦ | 執行期轉換(可能失敗的剖析/強制轉型) |
∪ | 內嵌聯集型別(T ∪ 無) |
比較#
| 符號 | 意義 |
|---|---|
≡ ≠ | 精確相等與不相等 |
≅ ≇ | 提升後精確相等——同值、相容的數值型別 |
< > ≤ ≥ | 順序比較 |
≈ ≉ | 模糊相等——依 isclose 預設容差匹配 |
邏輯與位元運算#
| 符號 | 意義 |
|---|---|
∧ ∨ ⊻ ¬ | 且、或、互斥或、非 |
⇐ ⇒ | 左移與右移 |
指派更新#
| 符號 | 意義 |
|---|---|
← | 運算式中唯一的指派運算子 |
⊕ ⊖ | 後置遞增/遞減述句(僅限可變的 整數) |
選用鏈結與非空斷言#
| 符號 | 意義 |
|---|---|
? ?. ?[ ?( | 選用鏈結 |
! !. ![ !( | 非空斷言 |
範圍#
| 符號 | 意義 |
|---|---|
‥ | 不包含終點的範圍端點 |
… | 包含終點的範圍端點 |
字面值分隔符#
| 符號 | 型別 | 作用 | |
|---|---|---|---|
' | ascii | 固定的機器符號 | |
" | 文字 | 行字串 | |
« » | 文字 | 區塊字串(書名號) | |
` | forma | 擷取的範本 | |
| ` | ` | 位元組 | 十六進位字面值 |
§ | 範本插槽 | "…"、«…»、 … 內的預留位置 |
標點符號#
| 符號 | 作用 |
|---|---|
( ) | 分組與呼叫 |
{ } | 區塊、類型 字面值或 JSON 文件 |
[ ] | 清單字面值與索引 |
. | 成員存取 |
, | 分隔符 |
; | 述句分隔符 |
: | JSON 欄位分隔符 |
= | 結構欄位形狀(不是執行期指派) |
@ | 註解標記 |
# | 行註解 |
Latin vocabulary and structural glyphs#
三個訊號選擇,讓 Faber 原始碼一眼即可辨識。
Faber 有意採用三個彼此協作的訊號選擇,打造出語法形狀穩定的原始碼。讀者無須先知道程式碼將編譯至哪個目標後端,就能看出每個建構的語意角色。
三個訊號#
| 訊號 | 範例 | 角色 |
|---|---|---|
| 型別優先宣告 | 文字 名稱、整數 aetas | 形狀朝向綁定——先型別,再名稱。 |
| 拉丁文行為詞 | 函式、類型、若、傳回、定值 | 宣告、陳述式、生命週期與行為意圖。 |
| 結構字形 | ← → ∴ ≡ ∪ ⇥ | 值流、型別流與結構接點——通用,永不在地化。 |
這三者經過設計,能彼此強化。熟悉某個語系的 Faber 讀者,可以閱讀任何語系的內容,因為字形與結構永遠不變。熟悉 Rust 後端的讀者,也仍能辨識 Faber 原始碼,因為拉丁文關鍵字與型別優先的順序,會產生獨特的視覺風格。
型別優先宣告#
Faber 在每個宣告中都將型別放在名稱之前。這與主流 C 家族語法相反,而且是刻意如此:
| 建構 | C 家族慣例 | Faber |
|---|---|---|
| 變數 | int count = 0 | 整數 count ← 0 |
| 函式 | fn greet(name: String) → String | 函式 salve(文字 名稱) → 文字 |
| 參數 | (String name) | (文字 名稱) |
型別優先宣告讓資料的形狀成為讀者首先看到的內容。這自然符合按語意廣度由左至右閱讀的語言——中文、印地語與阿拉伯語的宣告也遵循相同順序。
函式 divide(整數 a, 整數 b) → 整數 ∪ 無 {
若 b ≡ 0 則 傳回 可空
傳回 a / b
}拉丁文行為詞彙#
Faber 使用拉丁文詞彙表示每個具有行為或文法形狀的建構。這套詞彙規模小且規則一致,取自單一的古典來源,而非多數程式語言所採用的混合詞源。
宣告#
| 關鍵字 | 角色 | 約略對應 |
|---|---|---|
函式 | 宣告具名函式或方法 | fn、def、function |
類型 | 宣告帶有欄位的具體型別 | class、struct |
待實作介面 | 宣告行為契約 | interface、trait |
型別 | 宣告型別別名 | typedef、type |
分支聯集 | 宣告標籤聯合 | enum、sum type |
綁定與轉移#
| 關鍵字 | 角色 | 約略對應 |
|---|---|---|
定值 | 不可變綁定(寫入一次) | let、const |
變值 | 可變綁定 | let mut、var |
設為 | 簡潔的推導型別不可變綁定 | let(推導型別) |
傳回 | 從函式傳回值 | return |
拋出 | 在錯誤通道上拋出錯誤 | throw、raise |
崩潰 | 延後處理——尚未能表達的行為 | unimplemented!、todo |
控制流程#
| 關鍵字 | 角色 | 約略對應 |
|---|---|---|
若 | 條件分支 | if |
否則若 | 其他條件分支 | else if |
否則 | 其他分支 | else |
當 | While 迴圈 | while |
遍歷 | 迭代(值、鍵或範圍) | for |
選擇 | 模式比對(第一個分支優先) | match、switch |
執行 | 具錯誤復原的嘗試區塊 | try、do |
捕捉 | 執行 的錯誤處理器 | catch |
拉丁文詞彙是可綁定的——它隨附於標準詞彙包,但可透過讀者語系重新映射。泰語程式設計師會看到
ถ้า而不是若;中文程式設計師會看到函數而不是函式。詞彙並不享有特權;只有文法不變。
結構字形#
行為詞彙使用拉丁文,而結構意義使用通用字形。這些字形永不在地化,也不會在不同轉譯中改變意義。無論關鍵字以哪種人類語言呈現,它們都是讓 Faber 原始碼保持可辨識的視覺錨點。
值流#
| 字形 | 意義 |
|---|---|
← | 執行期綁定、重新指派與變異——唯一的指派運算子 |
→ | 函式回傳型別宣告 |
⇥ | 替代出口:錯誤通道型別或行內轉換復原 |
∴ | 閉包連接符 — 將閉包體與其簽名相連 |
型別形狀#
| 字形 | 意義 |
|---|---|
∷ | 靜態型別標註——對值型別的編譯期斷言 |
↦ | 執行期轉換——可能失敗的解析或強制轉型 |
∪ | 行內聯合型別——連接兩個型別(例如 T ∪ 無) |
比較與邏輯#
| 字形 | 意義 |
|---|---|
≡ ≠ ≢ | 精確相等與不相等——必須符合嚴格型別 |
≅ ≇ | 提升後精確相等——數值寬度合併後精確比較 |
≈ ≉ | 模糊相等——依 isclose 預設容差匹配 |
< > ≤ ≥ | 順序比較 |
∧ ∨ ⊻ ¬ | 邏輯與位元運算:且、或、異或、非 |
綁定慣例很重要#
有一個字形選擇值得特別注意,因為它是新讀者最常混淆的地方:
| 字形 | 角色 | 用於 |
|---|---|---|
← | 執行期流動 | 執行時的初始綁定、重新指派與變異 |
= | 結構形狀 | 常值中的欄位名稱與宣告中繼資料——不是執行期儲存 |
多數語言會重載 =,同時表示「在型別中定義此欄位」與「將執行期值放入此變數」。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 欄位會針對每個不同的語意工作使用不同的字形或關鍵字——不進行重載。
| 語意工作 | 其他語言常見寫法 | Faber |
|---|---|---|
| 參數型別宣告 | name: String | 文字 名稱 |
| 回傳型別 | → String、: String | → 文字 |
| 執行期指派 | x = value | ← |
| 相等測試 | == | ≡ |
| 可空性 | T?、Option<T> | T ∪ 無 |
| 分支加上單一陳述式 | if (cond) return x | 若 cond 則 傳回 x |
| 型別轉換 | (T)value、value as T | value ∷ T |
| 轉換(可能失敗) | try_into() | value ↦ T |
參考資料#
- EBNF 文法——完整的字形與關鍵字清單
- examples/corpus/——包含所有關鍵字的語言語料庫,共有 292 個範例檔案
- examples/corpus/operatores/——運算子與字形範例
- Commandments——維持這些訊號的九項設計法則
Canonical vs sugar surfaces#
多個可解析表面,共用一個語意形狀。
Faber 設計中反覆出現一種模式:語言為每個建構定義一種規範拼寫,但也接受多種語意相同的語法糖拼寫。編譯器不偏好其中任何一種——兩者都會解析為相同的 AST 節點。格式化工具會根據上下文與模式決定要輸出哪一種拼寫。
規則:語法糖拼寫在語意上等同於長形式。 多個表面會解析為相同的
HirAnnotation或型別節點。faber format --canonical偏好規範拼寫;作者模式則保留作者所寫的語法糖。
數值型別語法糖#
數值型別具有長形式的規範拼寫,以及精簡的語法糖形式。 選擇以模組為單位,而不是以儲存庫為單位——CLI 套件可以全面使用長形式,而張量核心模組則可以使用語法糖:
| 語法糖 | 規範形式 | 領域 |
|---|---|---|
tf32、tf32[4]、ti64[2, 3] | 張量<f32, _>、張量<f32, [4]> | 密集張量——t + 寬度 + 可選形狀 |
sf32、sf32[2, 3]、si64[N] | 稀疏<f32, _>、稀疏<f32, [2, 3]> | 稀疏張量——s + 寬度 + 可選形狀 |
mf32[4, 4]、mu32[3, 3] | 矩陣<f32, [4, 4]> | 暫存器類別矩陣——m + 寬度 + 形狀 |
lf32、lu32、li64 | 列表<f32>、列表<u32> | 清單——l + 寬度 |
一般 Faber(偏好長形式):
入口 {
定值 列表<f32> values ← 空集
定值 張量<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)註解語法糖#
Faber 註解遵循與數值型別相同的雙表面模型。
註解是附加至宣告的編譯器管理中繼資料——例如 CLI 選項定義的
@ 選項,或非同步函式的 @ 未來。
規範形式:具有明確欄位名稱的花括號記錄:
@ 選項 {
binding = verbose,
簡 = "v",
詳 = "verbose",
型別 = 布林,
全局 = 真,
描述 = "Enable verbose output"
}語法糖形式:位置引數與具名別名:
@ 選項 verbose 簡 "v" 詳 "verbose" 型別 布林 全局 描述 "Enable verbose output"兩種形式都會產生相同的 HirAnnotation 記錄。規範形式明確且便於自我說明;語法糖形式則適用於欄位順序已廣為人知的常用註解,因此更為精簡。
faber format --canonical 偏好花括號記錄;作者模式則保留作者選擇的形式。
作者與規範格式化#
faber format 指令以兩種模式運作,對應規範與語法糖原則:
| 模式 | 指令 | 輸入 | 輸出 |
|---|---|---|---|
| 作者 | faber format | 已解析的 AST + 開頭雜項 | 保留 # 註解、空白行與語法糖拼寫的 Faber 原始碼 |
| 規範 | faber format --canonical | 已分析的 HIR + TypeTable | 正規化的 Faber——無註解、使用規範拼寫、不含語法糖 |
兩種模式都會經過編譯器完整的前半部流程(詞法分析、解析;規範模式另含分析)。無效原始碼會產生編譯器診斷——格式化工具不會默默格式化損壞的輸入。
兩種模式共同遵循的主要規則:
- 四個空格縮排
- Stroustrup 大括號:開啟的
{與控制標頭位於同一行 - 作者模式保留空白行的存在與否,但會將多於一個的連續空白行折疊
- 作者模式不會插入來源中不存在的空白行
- 規範模式會將型別拼寫正規化為長形式、將張量語法糖正規化為規範形式,並將註解正規化為花括號記錄
- 規範模式會對可為空的聯集輸出
T ∪ 無,並對可選參數輸出可選
設計原則#
規範與語法糖模式會出現在多個地方,是因為這是一項刻意的設計原則,而不是一組零散的一次性便利功能:
| 領域 | 規範 | 語法糖 |
|---|---|---|
| 張量型別 | 張量<f32, [4]> | tf32[4] |
| 註解 | @ 選項 { binding = verbose } | @ 選項 verbose ... |
| 格式化 | faber format --canonical | faber format(作者模式) |
| 讀者語系 | 拉丁文(la) | 任一語系套件 |
這個模式服務於兩個目標。第一,它降低入門門檻——新使用者可以直接撰寫 tf32[4],而不必輸入
張量<f32, [4]>。第二,它讓規範語言保持明確無歧義——當精確度很重要時,長形式會清楚表達其確切含義。格式化工具則在兩者之間搭起橋樑:作者撰寫語法糖,審閱者可以要求規範形式,而 CI 可以強制執行其中任一形式。
參考資料#
radix/docs/design/numeric-type-sugar.md— 完整語法糖系列、拼寫偏好radix/docs/design/annotation-sugar.md— 雙表面註解模型radix/docs/design/faber-canonical-surface.md— 作者與規範格式政策faber/docs/EBNF.md— 語法糖形式的文法表格