Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions content/fer/attributes/zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Fer 注解


## 语法

使用 `#[...]` 定义注解:

```fer
#[test]
check-username = () -> bool {
true
}
```

注解必须位于被注解项之前,并且每个注解占一行。注解参数使用 Fer/FON 的值语法:

```fer
#[workgroup-size = [8, 8, 1]]
compute-main = (global-id: Vec3<u32>) -> void {
// GPU compute body
}
```

注解内容必须在编译期可解析。未知注解必须被报告为错误,除非模块通过显式扩展注册表声明它是可忽略的文档注解。

## 字段注解

注解可以附着到结构体字段:

```fer
VertexInput: struct {
#[location = 0, interpolate = flat]
position: Vec3<f32>

#[location = 1]
color: Vec3<f32>
}
```

字段注解的键和值必须由所属后端或类型 scheme 定义。GPU location、插值模式和布局规则不能通过字符串拼接或运行时反射替代。

## 测试注解

`#[test]` 标记测试函数:

```fer
#[test]
check-username = () -> bool {
true
}
```

测试函数必须是无参数、可重复执行且具有明确结果的函数;测试失败时,工具应提供源文件、测试名和断言上下文。测试是否允许返回 `void`、如何隔离区域内存和如何表达参数化测试,仍待定。

## 后端注解

后端注解可以描述调用约定、GPU 工作组、外部接口或布局。后端注解必须只在目标后端启用时生效,并且在不支持该后端时给出明确诊断:

```fer
#[workgroup-size = [8, 8, 1]]
compute-main = (global-id: Vec3<u32>) -> void {
// 待定:WebGPU 后端的主体语义
}
```

实现不得把后端注解当作普通运行时数据;注解不应引入隐式全局状态。

## 注解参数

注解参数必须是布尔值、数值、字符串、数组、对象或已注册枚举值。动态表达式、函数调用、文件读取和网络请求不得出现在注解参数中。

注解键采用 kebab-case。相同注解是否可以重复、重复注解如何合并,以及未知参数是否允许,必须由注解定义明确声明;默认情况下重复注解和未知参数都是错误。

## 相关主题

- [类型系统](../types/zh-hans.md)
- [实现后端](../backends/zh-hans.md)
- [格式化规范](../formatting/zh-hans.md)
63 changes: 63 additions & 0 deletions content/fer/backends/zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Fer 实现后端


## 后端分层

编译器或运行时应按以下层次组织:

| 层 | 责任 |
| --- | --- |
| 解析器 | 把 UTF-8 源文本转换为语法树,并报告词法/语法错误 |
| 语义分析 | 解析模块、名称、类型、scheme、Must-use 和迁移规则 |
| 中间表示 | 表达与目标架构无关的值、区域、调用和控制语义 |
| 后端 | 将中间表示映射到解释器、LLVM、JVM、BEAM 或 WebGPU |
| 运行时 | 提供 I/O、区域分配、并发、诊断和平台能力 |

后端不得跳过语义分析来“尽力运行”不完整的 Fer 程序。开发模式可以提供恢复性诊断,但生产构建必须只接受通过规范检查的程序。

## 解释器

Fer Interpreter 用于快速反馈、工具链和 native fer browser 场景。解释器必须遵循与 AOT 相同的名称解析、类型检查、块返回值、Must-use、字符串视图和区域生命周期规则。解释器不得因为动态环境而引入隐式变量或动态字段。

## LLVM AOT

LLVM 后端可以使用 LLVM IR 进行 AOT 编译。LLVM 的整数、指针、调用约定和布局只是实现细节;Fer 类型的可观察范围由 Fer 规范决定。任何平台特有的布局都必须通过 ABI 注解或后端接口显式声明。

AOT 构建必须记录目标三元组、优化级别、规范版本和运行时版本。相同输入和构建配置应当能够复现可审查的产物元信息。

## JVM 与 BEAM 字节码

JVM 和 BEAM 后端可以把 Fer 映射到各自的字节码与运行时,但不得将 Fer 变量、垃圾回收或异常模型直接暴露为语言语义。若目标运行时提供自动内存管理,适配层仍需维持 Fer 的区域和所有权边界,或明确标注尚未满足的实验性能力。

## WebGPU

WebGPU 相关函数、结构体布局和工作组参数通过注解表达:

```fer
#[workgroup-size = [8, 8, 1]]
compute-main = (global-id: Vec3<u32>) -> void {
// 具体 GPU 语义待定
}
```

GPU 后端必须检查字段 location、对齐、可传输类型、工作组大小和资源绑定。不能映射到 WebGPU 的 Fer 能力必须在编译期拒绝,而不是生成隐式 CPU 回退。

## 后端一致性测试

每个后端应运行相同的规范测试集。测试至少覆盖:

- 整数范围、浮点边界和字符串 UTF-8 行为。
- 模块导入、导出、UFCS 和重命名。
- 块返回值、match 穷尽性和 Must-use。
- 结构体默认值、枚举变体、`Option` 和精炼类型。
- 区域生命周期、越界、错误路径和资源释放。
- FON 解析、scheme 验证和二进制序列化边界。

后端差异必须归因于明确的非规范化行为,并提供失败位置和最小复现输入。

## 相关主题

- [类型系统](../types/zh-hans.md)
- [注解](../attributes/zh-hans.md)
- [内存与性能](../memory-and-performance/zh-hans.md)
- [迁移机制](../migration/zh-hans.md)
171 changes: 171 additions & 0 deletions content/fer/expressions/zh-hans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Fer 表达式


## 求值模型

表达式产生一个值,或产生无值结果。实现可以优化求值顺序,但不得改变可观察结果、错误诊断或资源安全边界。任何具有副作用的操作都必须在其所属库的接口中明确说明。

一个块的值严格等于其最后一行表达式的值:

```fer
location = {
lat = 120
lng = 30
{ lat = lat, lng = lng }
}
```

如果最后一行是绑定操作,则该块不返回实质性值:

```fer
{
temporary = create-resource()
close-resource(temporary)
}
```

## Must-use 规则

如果块产生了 `string`、整数、结构体、枚举或其他实质性值,该值必须被绑定、作为参数传递、作为返回值返回,或显式交给一个消费函数。表达式不得悬空:

```fer
// 合法:值被绑定
message = format-user(user)

// 合法:值作为参数传递
print(format-user(user))

// 非法:结果被丢弃
format-user(user)
```

返回 `void` 的调用可以单独成行。实现不能仅凭函数名判断调用是否有值,必须根据函数签名和类型系统应用 Must-use 规则。

## Condition 表达式

condition 表达式返回 `bool`。比较词和符号是等价写法;项目应使用格式化工具的默认形式,不得在同一代码库中人为混用两套风格。

| 语义 | 词法形式 | 符号形式 | 适用类型 |
| --- | --- | --- | --- |
| 小于 | `less` | `<` | number |
| 大于 | `more` | `>` | number |
| 至少 | `least` | `>=` | number |
| 至多 | `most` | `<=` | number |
| 包含 | `contains` | 无 | string |
| 相等 | `equals` | 无 | string、number 或可比较类型 |
| 成员 | `in` | 无 | array 或集合 |
| 匹配 | `matches` | 无 | string 与 regex |
| 前缀 | `starts` | 无 | string |
| 后缀 | `ends` | 无 | string |
| 逻辑非 | `not` | `!` | bool |

**Quantifier** 组合多个 condition expression:

| 量词语法 | 数学含义 | 对应命令式 | 业务意图 |
| :--- | :--- | :--- | :--- |
| **`all ( ... )`** | 全部为真(∀) | `AND` / `&&` | 所有条件必须全部满足 |
| **`any ( ... )`** | 至少一个为真(∃ ≥ 1) | `OR` / `\|\|` | 命中任意一个即可 |
| **`one ( ... )`** | 恰好只有一个为真(∃ = 1) | `XOR` / 异或 | 排他互斥(有且仅有一个) |
| **`none ( ... )`** | 全部为假(∃ = 0) | `NOR` / `!any` | 所有条件绝不能命中 |

`all`、`any`、`one` 和 `none` 统称为 **Quantifier**(量词)。Quantifier 的形式为 `quantifier ( condition-expression-list )`,其中 `quantifier` 必须是这四个名称之一。内部 condition expression 无需额外加括号;Quantifier 遵循与 FON 相同的通用元素分隔规则:逗号 `,` 与换行 `\n` 均为合法分隔符,单行、多行和逗号与换行混合的分组都具有相同语义。列表中的表达式可以继续嵌套 Quantifier。`all`、`any` 和 `none` 可以在确定结果后短路;`one` 在已经确认有两个满足条件的表达式后可以短路。condition 表达式应保持纯语义,因此实现不得让短路优化改变可观察结果或资源安全边界。

示例:

```fer
/* All must match: */
can-access = all (
user.is-logged-in

/* At least one: */
any (
user.role equals .admin
user.reputation >= 100
)

/* Exactly one: */
one (
payment.is-credit-card
payment.is-crypto
)

/* None allowed: */
none (
user.is-banned
user.is-suspended
)
)

is-following = any (
user.relationship equals .follower
user.relationship equals .friend
)

/* Single-line Quantifier: */
cond = all (x > 10, y < 10, not (z contains `123`))

/* Multi-line Quantifier: */
cond = all (
x > 10
y < 10
not (z contains `123`)
)

/* Mixed separators are also valid: */
cond = all (a > 1, b > 2
c < 3)

is-text = not (comment.content matches `\\btx(|et|t|.*)\\b`)
```

`and`、`or` 和 `xor` 不再是 Fer 关键字;组合多个 condition expression 时,必须使用 `all`、`any`、`one` 或 `none` Quantifier。逗号 `,` 与换行 `\n` 都是合法的通用元素分隔符,Parser 必须将单行纯逗号、多行纯换行以及逗号与换行混合的 Quantifier 解析为等价的条件序列。CST 必须保留原始物理排版,以支持无损还原。

## Match 表达式

match 以一个表达式作为输入,并按分支顺序返回第一个匹配分支的值。分支使用大括号表示:

```fer
age = 20
category = age {
< 18 { `minor` }
> 60 { `old` }
{ `adult` }
}
```

最后一个没有模式的分支是默认分支。没有匹配分支且没有默认分支时,编译器必须报告非穷尽匹配;不得隐式返回空值。

condition 结果也可以作为 match 输入:

```fer
label = any (
comment.content matches `regex`
comment.content contains `xxx`
) {
true { `匹配或包含` }
{ `未匹配到` }
}
```

模式分支的结果必须具有可统一的类型,或者显式声明为共同的枚举、结构体或 `Option`。分支内部同样遵循块返回值和 Must-use 规则。

## 成员访问和调用

成员访问使用点号。若成员后面是调用括号,则它可能触发 UFCS 解析;完整规则见 [函数与调用](../functions/zh-hans.md):

```fer
io.stdout.writer().write(bytes = `Zero cost abstraction`)
```

成员访问不得动态创建字段。访问未知字段、访问私有字段或把函数当作值使用但缺少显式函数类型时,必须报告编译期错误。

## 条件与副作用

condition 和 match 的判断表达式应当是纯表达式。需要执行 I/O、锁、网络或资源释放时,应调用明确命名的函数,并让其返回值遵循 Must-use 规则。实现不得把条件分支的求值改写成会额外执行副作用的形式。

## 相关主题

- [函数与调用](../functions/zh-hans.md)
- [类型系统](../types/zh-hans.md)
- [字符串](../strings/zh-hans.md)
- [Fer 语法基础](../syntax/zh-hans.md)
Loading