Types and values
Data types#
Faber 拥有静态、类型优先的类型系统。每个声明都把类型放在名称之前:textus nomen,而不是 nomen: textus。类型系统涵盖标量原语、泛型集合、定宽数值、张量,以及面向 GPU 的寄存器类型。
原语类型#
| 类型 | 作用 | 示例字面量 |
|---|---|---|
文本 | Unicode 字符串 | "Salve, munde" |
ascii | 固定机器令牌 | 'solum:lege' |
整数 | 有符号整数(默认 i64) | 42 |
小数 | 浮点数(默认 f64) | 3.14 |
布尔 | 布尔值 | 真, 假 |
无值 | 单元类型 / 无值 | — |
空 | 空值 / 缺失 | 空 |
时刻 | 时长 / 时间点 | — |
json | 编译期 JSON 值 | { "key": "value" } |
字节 | 十六进制字节序列 | \|00ff\| |
定宽数值类型#
整数 和 小数 拥有默认位宽(i64 和 f64)以及显式位宽形式:
常量 整数<i32> narrow ← 7 ∷ 整数<i32>
常量 整数<u64> wide ← 255 ∷ 整数<u64>
常量 f32 single ← 1.5 ∷ f32类型位置支持位宽简写:i8 … u64、f16、f32、f64 等价于 numerus<W> / fractus<W>。
可空类型#
可空值使用联合语法 T ∪ nihil:
函数 find(文本 key) → 整数 ∪ 空 {
返回 空
}
函数 maybe() → 文本 ∪ 空 {
返回 空
}Faber 中没有 T? 或 Option<T> 语法。联合是显式的。
类型别名#
类型 UserId = 整数泛型#
函数、类型别名、类 和 implendum 接受使用 <T> 语法的类型参数:
函数 identitas<T>(T valor) → T {
返回 valor
}
函数 primum<T>(列表<T> res) → T ∪ 空 {
返回 res.primus()
}支持在调用处显式指定类型参数:
函数 identitas<T>(T valor) → T {
返回 valor
}
常量 整数 value ← identitas<整数>(7)集合#
| 类型 | 作用 | 简写 |
|---|---|---|
lista<T> | 有序动态集合 | lf32, lu32 |
tabula<K, V> | 键值映射 | — |
tensor<T, Figura> | 稠密定形缓冲区 | tf32[4], ti64[2,3] |
sparsa<T, Figura> | 稀疏定形缓冲区 | sf32[4], si64[2,3] |
intervallum | 区间类型 | — |
copia<T> | 无序集合 | — |
cursor<T> | 惰性流 | — |
常量 列表<整数> nums ← [1, 2, 3]
常量 映射<文本, 整数> scores ← { "alice": 10, "bob": 20 }张量类型#
tensor<T, Figura> 是稠密定形容器:
| 形式 | 含义 |
|---|---|
tensor<T, Figura> | 规范写法 |
tensor<T, []> | 0 阶(标量容器) |
tensor<T, _> | 形状推断占位符 |
tensor<T, [N]> | 1 阶向量 |
tensor<T, [N, M]> | 2 阶矩阵 |
常量 张量<f32, []> scalar ← 空集
常量 张量<整数, [4]> vector ← [1, 2, 3, 4] ↦ 张量<整数, [4]>
常量 整数 ∪ 空 first ← vector[0]GPU 核心类型#
这些类型由系统通道识别,用于 GPU 和寄存器相关工作。缺乏硬件支持的包目标会拒绝它们:
函数 half(f16 x) → f16 {
返回 x
}
函数 add(矩阵<f32, [2, 2]> a, 矩阵<f32, [2, 2]> b) → 矩阵<f32, [2, 2]> {
返回 a.addita(b)
}
函数 swap(原子<整数<i32>> cell, 整数<i32> value) → 整数<i32> {
返回 cell.exchange(value)
}类型上的借用标记#
借用标记(借自、传入、取自)可以出现在参数位置的类型上,用于表示值的传递方式:
# shared borrow — caller retains ownership
functio imprime(de textus label) → vacuum { }
# mutable borrow — caller lends mutable access
functio duplica(in numerus value) → vacuum { }
# move — caller gives up ownership
functio consume(ex textus buffer) → textus {
redde buffer
}比较策略#
| 运算符 | 家族 | 行为 |
|---|---|---|
≡, ≠ | 精确相等 | 要求类型完全相同;空 旁路 |
≈, ≉ | 数值相等 | 仅限数值格 |
<, ≤, >, ≥ | 排序 | 数值、时间点、标量文本 |
intra | 区间包含 | 数值在区间内 |
inter | 集合归属 | 元素在集合中 |
Variables and binding#
Faber 拥有三个变量关键字和一个专门的赋值符。核心区别在于 常量(一次写入)与 变量(可自由重赋值),以及 ←(运行时流)与 =(结构体字段形状)。
fixum — 不可变绑定#
常量 绑定只能写入一次。声明时可带或不带初始化式;若声明时不带,则必须在读取之前精确赋值一次。第二次赋值会被拒绝。
常量 整数 count ← 0
常量 文本 name ← "Marcus"
常量 列表<整数> inferred ← [1, 2, 3]延迟初始化:
入口 {
常量 整数 factor
如果 真 {
factor ← 10
}
否则 {
factor ← 100
}
显示 factor
}varia — 可变绑定#
变量 绑定可自由重赋值:
入口 {
变量 整数 count ← 0
count ← count + 1
count ← count * 2
}sit — 推断不可变语法糖#
sit 是 fixum _ 的语法糖——一种类型推断的不可变绑定:
入口 {
常量 文本 salve ← "Salve"
常量 文本 nomen ← "Marcus"
常量 整数 x ← 42
# Deferred form
常量 文本 label
label ← "deferred"
}运行时绑定与结构体定义#
Faber 将大多数语言合并为 = 的语义拆分为两种:
| 符号 | 角色 | 用途 |
|---|---|---|
← | 运行时流 | 初始绑定、重赋值、变更 |
= | 结构形状 | 字面量与元数据内的字段名 |
类 Point {
整数 x
整数 y
}
入口 {
# Runtime: ← attaches a value to a name at execution time
变量 整数 count ← 0
变量 文本 label ← "ready"
count ← count + 1
# Structural: = defines field values inside a type literal
常量 Point p ← Point {x = 10, y = 20}
}ex 字段提取#
取自 将值的字段提取为局部绑定:
类 Persona {
文本 nomen
整数 aetas
}
入口 {
常量 Persona p ← Persona {nomen = "Marcus", aetas = 30}
常量 文本 nomen ← p.nomen
常量 整数 aetas ← p.aetas
# prints "Marcus"
显示 nomen
}后缀自增与自减#
⊕ 和 ⊖ 是用于可变 整数 位置的后缀自增/自减语句。它们仅作为语句使用——没有表达式值,也没有前缀形式:
入口 {
变量 整数 i ← 0
# i becomes 1
i ⊕
# i becomes 0
i ⊖
}Collections#
Faber 拥有多种由编译器内置的集合类型。其规范方法位于编译器中,而非标准库中。
Lista — 有序动态集合#
常量 列表<整数> empty ← 空集
常量 列表<整数> numbers ← [1, 2, 3, 4, 5]
常量 列表<文本> names ← ["Marcus", "Julia", "Gaius"]
常量 列表<列表<整数>> nested ← [[1, 2], [3, 4]]使用 sparge 展开:
常量 列表<整数> a ← [1, 2, 3]
常量 列表<整数> b ← [4, 5, 6]
常量 列表<整数> combined ← [展开 a, 展开 b]
常量 列表<整数> headed ← [0, 展开 a, 99]关键方法:longitudo、accipe、appende、summa、primus、novissimus。
Tabula — 键值映射#
常量 映射<文本, 整数> scores ← { "alice": 10, "bob": 20 }Tensor — 密集定形缓冲区#
常量 张量<f32, []> scalar ← 空集
常量 张量<整数, [4]> vector ← [1, 2, 3, 4] ↦ 张量<整数, [4]>
常量 整数 ∪ 空 first ← vector[0]Tensor 语法糖(用于数值密集型代码):
常量 张量<f32, []> seed ← 空集
常量 张量<f32, [4]> lanes ← seed.strue([1.0, 2.0, 3.0, 4.0], [4])关键方法:forma、accipe、ponde、crea、structa、strue,以及逐元素算术、矩阵乘法(multiplicatio)和归约(summa、productum)。
Sparsa — 稀疏定形缓冲区#
常量 稀疏<f32, [2, 3]> sparse ← 空集
入口 {
sparse.ponde([0, 1], 4.0)
sparse.ponde([1, 2], 9.0)
# accipe returns the stored value, here 4.0
显示 sparse.accipe([0, 1])
# count of stored entries
显示 sparse.nonnihil()
}密集与稀疏之间的转换:
常量 张量<f32, [2, 2]> dense ← [[1.0, 0.0], [0.0, 2.0]] ↦ 张量<f32, [2, 2]>
常量 稀疏<f32, [2, 2]> sparse ← dense ↦ 稀疏<f32, [2, 2]>
常量 张量<f32, [2, 2]> roundtrip ← sparse ↦ 张量<f32, [2, 2]>游标 — 惰性流#
cursor<T> 是一种惰性流类型。可由集合迭代器、tuus 视图或生成器函数创建。通过 itera ex 消费:
常量 列表<整数> items ← [1, 2, 3]
入口 {
遍历 取自 items 常量 item {
显示 item
}
}Intervallum — 范围#
入口 {
# exclusive range: 0, 1, 2, 3, 4
遍历 范围 0‥5 常量 i {
显示 i
}
# inclusive range: 0, 1, 2, 3, 4, 5
遍历 范围 0…5 常量 i {
显示 i
}
}‥ 是排他范围的端点;… 是包含端点。
String and template literals#
Faber 使用分隔符语义 — 每种引号形式表示不同的源代码形态。它们之间不能互换。
字面量形式#
| 形式 | 类型 | 角色 | ||
|---|---|---|---|---|
'…' | ascii | 固定机器令牌;无 §;无 (…) | ||
"…" | 文本 | 短 Unicode 单行字符串;(…) 渲染 | ||
«…» | 文本 | 块/多行 Unicode;(…) 渲染 | ||
… | forma | 捕获模板;(…) 捕获 | ||
{ … } | json | 编译期 JSON 文档 | ||
| ` | … | ` | 字节 | 编译期十六进制字节 |
[ … ] | lista<T> | Faber 列表字面量 |
字符串模板应用#
Faber 通过字符串模板应用格式化文本:一个带有 § 占位符的 "…" 或 «…» 字面量,后接括号参数:
函数 greet(文本 nomen) → 文本 {
返回 "Salve, §!"(nomen)
}
常量 整数 pagina ← 3
常量 整数 totum ← 10
常量 文本 code ← "200"
常量 文本 label ← "OK"
常量 文本 msg ← "Page § of §"(pagina, totum)
常量 文本 block ← "status: § (§)"(code, label)关键规则:
§(U+00A7) 是模板占位符- 位置占位符:
§0、§1、…… 用于显式排序 - 结尾的
!选择显示格式化:"Salve, §!"(nomen) (args)后缀是模板应用,不是函数调用
块字符串#
多行块使用书名号 «…»:
常量 文本 sql ← «
select id, email
from accounts
»捕获模板 (forma)#
反引号模板捕获文本和参数而不渲染。 对于绑定的 SQL/URL 载荷是安全的:
常量 整数 user_id ← 42
常量 forma query ← `select * from users where id = §`(user_id)内联 JSON#
裸 { … } 是内联 JSON:一个编译期的 json 文档,不是匿名的 Faber 对象。键是用 : 分隔的带引号字符串:
常量 json empty ← {}
常量 json user ← { "name": "Marcus", "age": 30, "active": true }
常量 json nested ← { "meta": { "version": 1 }, "tags": ["alpha", "beta"] }若要构造有类型的属,请使用类型名和 = 字段形态:
类 Point {
整数 x
整数 y
}
常量 Point p ← Point {x = 10, y = 20}Nullability and optionality#
Faber 在值层面区分"空缺"与声明位置的"可选提供"。
可空值 — T ∪ nihil#
当值可能缺失时,使用 T ∪ nihil:
函数 find(文本 key) → 整数 ∪ 空 {
返回 空
}
函数 divide(整数 a, 整数 b) → 整数 ∪ 空 {
如果 b ≡ 0 则 返回 空
返回 a / b
}可选声明槽 — sponte#
当参数或字段可由调用者或构造函数省略时,在名称之后使用 sponte:
函数 connect(文本 host, 整数 port 可选) → 无值 {
}
类 User {
文本 email 可选
}借用标记可与可选参数组合使用:
函数 process(借自 整数 depth 可选) → 无值 {
}非空断言 — !#
使用 !., ![, !( 来断言某个可空值不是 空:
类 Box {
整数 ∪ 空 val
}
常量 Box ∪ 空 maybe_name ← Box {val = 7}
常量 整数 ∪ 空 name ← maybe_name!.val对 空 进行非空断言会在运行时中止。
空值合并 — vel#
常量 文本 ∪ 空 provided ← 空
常量 文本 name ← provided 兜底 "default"ignotum#
ignotum 是用于应急通道和不完整知识的顶层未知类型。它不是一种可空性机制。
Conversion and construction#
两个重要的转换运算符,一个用于运行时,一个用于编译时:
# runtime conversion
常量 整数 parsed ← "42" ↦ 整数
# static ascription
常量 整数 value ← 7
常量 文本 text ← value ∷ 文本运行时转换 — ↦#
使用 ↦ 进行运行时转换,尤其是可能失败的解析或强制转换。用 ⇥ 提供内联恢复:
常量 文本 input ← "9"
常量 整数 n ← "42" ↦ 整数
常量 整数 safe ← input ↦ 整数 ⇥ 0类型驱动的具象化:
常量 文本 path ← "/etc/hosts"
常量 向量<f32, 4> lanes ← [1.0, 2.0, 3.0, 4.0] ↦ 向量<f32, 4>
常量 文本 body ← 调用 'solum:lege' (path) ↦ 文本静态标注 — ∷#
使用 ∷ 进行显式静态类型标注。它是后置的,并且由目标类型驱动:
常量 整数 value ← 7
常量 整数<i32> x ← 7 ∷ 整数<i32>
常量 文本 text ← value ∷ 文本空值合并 — vel#
当值为 空 时,使用 vel 进行空值合并:
常量 文本 ∪ 空 provided_name ← 空
常量 文本 name ← provided_name 兜底 "default"