Skip to content

Commit 4fde4d3

Browse files
committed
update docs
1 parent 219c94b commit 4fde4d3

6 files changed

Lines changed: 324 additions & 0 deletions

File tree

docs/RuleSpec.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,65 @@ For example, two different imported names that refer to the same definition are
124124
still different unless their parsed source spelling matches or a metavariable
125125
captures them.
126126

127+
### Let Shapes With Omitted Bodies
128+
129+
An ordinary `let` shape without an explicit body is a let-header pattern. For
130+
example, this shape matches the binding pattern and right-hand side, but does
131+
not constrain the candidate body:
132+
133+
```yaml
134+
patterns:
135+
- shape: let $(name:id) = $(value:exp)
136+
```
137+
138+
It can match candidates such as:
139+
140+
```moonbit
141+
let item = load()
142+
```
143+
144+
```moonbit
145+
let item = load(); use(item)
146+
```
147+
148+
```moonbit
149+
let item = load(); { trace(item); item }
150+
```
151+
152+
This exception exists because the MoonBit parser represents `let item = load()`
153+
as an `Expr::Let` whose body is a synthesized unit expression. When that
154+
synthesized unit appears in the pattern shape, the matcher treats it as "body
155+
omitted in the pattern" instead of requiring the candidate body to be the same
156+
unit node.
157+
158+
Write an explicit body when the body matters:
159+
160+
```yaml
161+
patterns:
162+
- shape: let $(name:id) = $(value:exp); use($(name:id))
163+
```
164+
165+
To capture whichever body the candidate has, write a body metavar explicitly:
166+
167+
```yaml
168+
patterns:
169+
- shape: let $(name:id) = $(value:exp); $(body:exp)
170+
```
171+
172+
To require a unit body, write an explicit `()` body:
173+
174+
```yaml
175+
patterns:
176+
- shape: let $(name:id) = $(value:exp); ()
177+
```
178+
179+
This matches an explicit unit body. It is not the same as the omitted-body
180+
shape above, which intentionally ignores the candidate body. Omitted-body-only
181+
matching is not currently expressible as a structural shape.
182+
183+
This shortcut applies only to ordinary `let` expressions. `let mut`, local
184+
function definitions, and `letrec` shapes use normal structural matching.
185+
127186
## Metavariables
128187

129188
Identifiers and labels in a shape are literal by default. A name becomes a

docs/RuleSpec_CN.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,62 @@ shape 是结构性的:
100100

101101
扫描器不会对 shape 做类型检查,也不会按语义解析名称。例如,两个不同的导入名称即使指向同一定义,仍然是不同的;除非它们解析后的源码拼写一致,或被元变量捕获。
102102

103+
### 省略 body 的 let shape
104+
105+
没有显式 body 的普通 `let` shape 是 let-header pattern。例如,下面的 shape
106+
会匹配绑定 pattern 和右侧表达式,但不会约束候选表达式的 body:
107+
108+
```yaml
109+
patterns:
110+
- shape: let $(name:id) = $(value:exp)
111+
```
112+
113+
它可以匹配下面这些候选形式:
114+
115+
```moonbit
116+
let item = load()
117+
```
118+
119+
```moonbit
120+
let item = load(); use(item)
121+
```
122+
123+
```moonbit
124+
let item = load(); { trace(item); item }
125+
```
126+
127+
这个例外来自 MoonBit parser 的表示方式:`let item = load()` 会被表示为
128+
`Expr::Let`,其 body 是一个合成的 unit 表达式。当 pattern shape 中出现这个合成
129+
unit 时,matcher 会把它视为“pattern 省略了 body”,而不是要求候选 body
130+
也必须是同一个 unit node。
131+
132+
如果 body 重要,请显式写出 body:
133+
134+
```yaml
135+
patterns:
136+
- shape: let $(name:id) = $(value:exp); use($(name:id))
137+
```
138+
139+
如果候选 body 可以是任意表达式,但你想捕获它,请显式写 body 元变量:
140+
141+
```yaml
142+
patterns:
143+
- shape: let $(name:id) = $(value:exp); $(body:exp)
144+
```
145+
146+
如果期望 body 是 unit,请显式写 `()` body:
147+
148+
```yaml
149+
patterns:
150+
- shape: let $(name:id) = $(value:exp); ()
151+
```
152+
153+
这会匹配显式 unit body。它不同于上面的省略 body shape;省略 body 的形式会有意忽略候选 body。当前结构 shape
154+
无法表达“只匹配语法上省略 body 的 let”。
155+
156+
这个快捷匹配只适用于普通 `let` 表达式。`let mut`、局部函数定义和
157+
`letrec` shape 使用普通结构匹配。
158+
103159
## 元变量
104160

105161
shape 中的标识符和标签默认都是字面量。只有在 `shape` 内使用内联元变量语法时,一个名称才会成为元变量;下面描述的内置通配符除外。

docs/WritingRules.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,57 @@ patterns:
148148
file or a fragment that only makes sense at module scope, rule compilation will
149149
fail.
150150

151+
### 1.1. Decide whether a `let` body matters
152+
153+
An ordinary `let` shape with no explicit body matches only the let header. This
154+
is useful when the binding itself is the interesting part:
155+
156+
```yaml
157+
patterns:
158+
- shape: let $(name:id) = $(value:exp)
159+
```
160+
161+
That shape can match all of these candidate forms because the body is ignored:
162+
163+
```moonbit
164+
let item = load()
165+
```
166+
167+
```moonbit
168+
let item = load(); use(item)
169+
```
170+
171+
```moonbit
172+
let item = load(); { trace(item); item }
173+
```
174+
175+
If the body matters, write it in the shape:
176+
177+
```yaml
178+
patterns:
179+
- shape: let $(name:id) = $(value:exp); use($(name:id))
180+
```
181+
182+
If the body can be anything but you want to capture it, add an explicit body
183+
metavar:
184+
185+
```yaml
186+
patterns:
187+
- shape: let $(name:id) = $(value:exp); $(body:exp)
188+
```
189+
190+
If you expect the body to be unit, write the unit body explicitly:
191+
192+
```yaml
193+
patterns:
194+
- shape: let $(name:id) = $(value:exp); ()
195+
```
196+
197+
Do not use `let $(name:id) = $(value:exp)` when you mean "the body is empty" or
198+
"the body is `()`"; the omitted-body form intentionally ignores whatever body
199+
the candidate has. Matching only syntactically omitted let bodies is not
200+
currently expressible as a structural shape.
201+
151202
### 2. Mark metavars inline in `shape`
152203

153204
Names in `shape` are literal by default, even if they look like placeholders.

docs/WritingRules_CN.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,54 @@ patterns:
8787
8888
`shape` 会作为单个 MoonBit 表达式片段解析。如果你粘贴整个文件,或只在模块作用域才有意义的片段,规则编译会失败。
8989

90+
### 1.1. 判断 `let` body 是否重要
91+
92+
没有显式 body 的普通 `let` shape 只匹配 let header。当你只关心绑定本身时,这很有用:
93+
94+
```yaml
95+
patterns:
96+
- shape: let $(name:id) = $(value:exp)
97+
```
98+
99+
因为 body 会被忽略,这个 shape 可以匹配下面所有候选形式:
100+
101+
```moonbit
102+
let item = load()
103+
```
104+
105+
```moonbit
106+
let item = load(); use(item)
107+
```
108+
109+
```moonbit
110+
let item = load(); { trace(item); item }
111+
```
112+
113+
如果 body 重要,请把它写进 shape:
114+
115+
```yaml
116+
patterns:
117+
- shape: let $(name:id) = $(value:exp); use($(name:id))
118+
```
119+
120+
如果 body 可以是任意表达式,但你想捕获它,请显式添加 body 元变量:
121+
122+
```yaml
123+
patterns:
124+
- shape: let $(name:id) = $(value:exp); $(body:exp)
125+
```
126+
127+
如果你期望 body 是 unit,请显式写 unit body:
128+
129+
```yaml
130+
patterns:
131+
- shape: let $(name:id) = $(value:exp); ()
132+
```
133+
134+
当你的意思是“body 为空”或“body 是 `()`”时,不要写
135+
`let $(name:id) = $(value:exp)`;省略 body 的形式会有意忽略候选表达式的任意 body。当前结构 shape
136+
无法表达“只匹配语法上省略 body 的 let”。
137+
90138
### 2. 在 `shape` 中内联标记元变量
91139

92140
`shape` 中的名称默认都是字面量,即使它们看起来像占位符。

docs/rule_spec.mbt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,65 @@ let _embed_rulespec_md : String =
128128
#|still different unless their parsed source spelling matches or a metavariable
129129
#|captures them.
130130
#|
131+
#|### Let Shapes With Omitted Bodies
132+
#|
133+
#|An ordinary `let` shape without an explicit body is a let-header pattern. For
134+
#|example, this shape matches the binding pattern and right-hand side, but does
135+
#|not constrain the candidate body:
136+
#|
137+
#|```yaml
138+
#|patterns:
139+
#| - shape: let $(name:id) = $(value:exp)
140+
#|```
141+
#|
142+
#|It can match candidates such as:
143+
#|
144+
#|```moonbit
145+
#|let item = load()
146+
#|```
147+
#|
148+
#|```moonbit
149+
#|let item = load(); use(item)
150+
#|```
151+
#|
152+
#|```moonbit
153+
#|let item = load(); { trace(item); item }
154+
#|```
155+
#|
156+
#|This exception exists because the MoonBit parser represents `let item = load()`
157+
#|as an `Expr::Let` whose body is a synthesized unit expression. When that
158+
#|synthesized unit appears in the pattern shape, the matcher treats it as "body
159+
#|omitted in the pattern" instead of requiring the candidate body to be the same
160+
#|unit node.
161+
#|
162+
#|Write an explicit body when the body matters:
163+
#|
164+
#|```yaml
165+
#|patterns:
166+
#| - shape: let $(name:id) = $(value:exp); use($(name:id))
167+
#|```
168+
#|
169+
#|To capture whichever body the candidate has, write a body metavar explicitly:
170+
#|
171+
#|```yaml
172+
#|patterns:
173+
#| - shape: let $(name:id) = $(value:exp); $(body:exp)
174+
#|```
175+
#|
176+
#|To require a unit body, write an explicit `()` body:
177+
#|
178+
#|```yaml
179+
#|patterns:
180+
#| - shape: let $(name:id) = $(value:exp); ()
181+
#|```
182+
#|
183+
#|This matches an explicit unit body. It is not the same as the omitted-body
184+
#|shape above, which intentionally ignores the candidate body. Omitted-body-only
185+
#|matching is not currently expressible as a structural shape.
186+
#|
187+
#|This shortcut applies only to ordinary `let` expressions. `let mut`, local
188+
#|function definitions, and `letrec` shapes use normal structural matching.
189+
#|
131190
#|## Metavariables
132191
#|
133192
#|Identifiers and labels in a shape are literal by default. A name becomes a

docs/writing_rules.mbt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,57 @@ let _embed_writingrules_md : String =
152152
#|file or a fragment that only makes sense at module scope, rule compilation will
153153
#|fail.
154154
#|
155+
#|### 1.1. Decide whether a `let` body matters
156+
#|
157+
#|An ordinary `let` shape with no explicit body matches only the let header. This
158+
#|is useful when the binding itself is the interesting part:
159+
#|
160+
#|```yaml
161+
#|patterns:
162+
#| - shape: let $(name:id) = $(value:exp)
163+
#|```
164+
#|
165+
#|That shape can match all of these candidate forms because the body is ignored:
166+
#|
167+
#|```moonbit
168+
#|let item = load()
169+
#|```
170+
#|
171+
#|```moonbit
172+
#|let item = load(); use(item)
173+
#|```
174+
#|
175+
#|```moonbit
176+
#|let item = load(); { trace(item); item }
177+
#|```
178+
#|
179+
#|If the body matters, write it in the shape:
180+
#|
181+
#|```yaml
182+
#|patterns:
183+
#| - shape: let $(name:id) = $(value:exp); use($(name:id))
184+
#|```
185+
#|
186+
#|If the body can be anything but you want to capture it, add an explicit body
187+
#|metavar:
188+
#|
189+
#|```yaml
190+
#|patterns:
191+
#| - shape: let $(name:id) = $(value:exp); $(body:exp)
192+
#|```
193+
#|
194+
#|If you expect the body to be unit, write the unit body explicitly:
195+
#|
196+
#|```yaml
197+
#|patterns:
198+
#| - shape: let $(name:id) = $(value:exp); ()
199+
#|```
200+
#|
201+
#|Do not use `let $(name:id) = $(value:exp)` when you mean "the body is empty" or
202+
#|"the body is `()`"; the omitted-body form intentionally ignores whatever body
203+
#|the candidate has. Matching only syntactically omitted let bodies is not
204+
#|currently expressible as a structural shape.
205+
#|
155206
#|### 2. Mark metavars inline in `shape`
156207
#|
157208
#|Names in `shape` are literal by default, even if they look like placeholders.

0 commit comments

Comments
 (0)