Skip to content

Commit 4414914

Browse files
committed
fix constant matching doc
1 parent fb5cbce commit 4414914

6 files changed

Lines changed: 60 additions & 25 deletions

File tree

TODO.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
an explicit kind for cross-position reuse, improving the diagnostic, or
99
adding a storage-path metavariable kind.
1010

11-
- Clarify constant matching in the RuleSpec overview. Constants are compared
12-
using the parser AST constant kind and preserved source spelling, so
13-
equivalent values such as `1000` and `1_000` do not necessarily match.
14-
Update the English and Chinese summaries so they do not imply that all
15-
formatting is ignored.
16-
1711
- Make the Chinese rule documentation available through the `docs` command,
1812
or document that only English documents are embedded. `docs/export.mbt`
1913
currently registers only `RuleSpec` and `WritingRules`; consider adding

docs/RuleSpec.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ rule authors can rely on today.
1515

1616
Rules use YAML format. Every `shape` value is MoonBit surface syntax. The scanner
1717
matches parsed MoonBit expression structure and does not match raw text.
18-
Formatting and comments are not significant. Expression form, operators,
19-
literal values, labels, callee names, and argument structure are significant.
18+
Whitespace formatting and comments are not significant. Literal source spelling
19+
is an exception: constants are compared by their parser AST kind and preserved
20+
source spelling, not by normalized semantic value. Equivalent values such as
21+
`1000` and `1_000` therefore do not necessarily match. Expression form,
22+
operators, labels, callee names, and argument structure are also significant.
2023
Wildcards and declared metavariables modify these matching requirements as
2124
documented below.
2225

@@ -130,13 +133,14 @@ It is one item and cannot represent a whole file or import list.
130133
Shapes are structural:
131134

132135
- undeclared identifiers and labels match literally
133-
- constants match by value
136+
- constants match by parser AST kind and preserved source spelling; equivalent
137+
values such as `1000` and `1_000` do not necessarily match
134138
- operators match literally
135139
- call and method-call argument kinds, labels, order, and arity must match
136140
- type annotations and type names in matched syntax must match where present
137-
- source locations and formatting do not participate in matching; top-level
138-
documentation is an AST field and follows the `inside-toplevel` matching
139-
mode
141+
- source locations, comments, and whitespace formatting do not participate in
142+
matching; top-level documentation is an AST field and follows the
143+
`inside-toplevel` matching mode
140144

141145
The scanner does not type-check shapes and does not resolve names semantically.
142146
For example, two imported names that refer to the same definition compare as
@@ -487,8 +491,9 @@ Qualified constructor identities include their extra info, such as `@pkg.Ctor`,
487491

488492
A `const` metavar captures a parsed MoonBit constant. In expression position,
489493
it matches `Expr::Constant`; in pattern position, it matches `Pattern::Constant`.
490-
It compares the parser AST constant kind and value only; it does not type-check
491-
or normalize equivalent values.
494+
It compares the parser AST constant kind and preserved source spelling; it does
495+
not type-check or normalize equivalent values. For example, `1000` and `1_000`
496+
do not necessarily compare as the same constant.
492497

493498
Example:
494499

docs/RuleSpec_CN.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
关键词 "must"、"must not"、"may" 和 "currently" 描述的是规则作者今天可以依赖的行为。
1212

13-
规则使用 YAML 格式。每个 `shape` 值都是 MoonBit 表面语法。扫描器匹配解析后的 MoonBit 表达式结构,不匹配原始文本。格式和注释不参与匹配。表达式形式、操作符、字面量值、标签、被调用名称和参数结构参与匹配。通配符和已声明元变量按下文规则修改这些匹配要求。
13+
规则使用 YAML 格式。每个 `shape` 值都是 MoonBit 表面语法。扫描器匹配解析后的 MoonBit 表达式结构,不匹配原始文本。空白排版和注释不参与匹配,但字面量的源码拼写是例外:常量按 parser AST 中的常量种类和保留的源码拼写比较,而不是按归一化后的语义值比较。因此,`1000``1_000` 不一定匹配。表达式形式、操作符、标签、被调用名称和参数结构也参与匹配。通配符和已声明元变量按下文规则修改这些匹配要求。
1414

1515
## 规则文件
1616

@@ -105,11 +105,12 @@ Taint `sources`、`sinks` 和 `sanitizers` 同样使用 `shape` 键。这些字
105105
shape 是结构性的:
106106

107107
- 未声明的标识符和标签按字面匹配
108-
- 常量按值匹配
108+
- 常量按 parser AST 中的常量种类和保留的源码拼写匹配;`1000`
109+
`1_000` 这样的等值常量不一定匹配
109110
- 操作符按字面匹配
110111
- 调用和方法调用的参数种类、标签、顺序和数量必须匹配
111112
- 匹配语法中出现的类型注解和类型名必须匹配
112-
- 源码位置和格式不参与匹配;顶层文档是 AST 字段,遵循
113+
- 源码位置、注释和空白排版不参与匹配;顶层文档是 AST 字段,遵循
113114
`inside-toplevel` 的匹配模式
114115

115116
扫描器不会对 shape 做类型检查,也不会按语义解析名称。例如,两个指向同一定义的导入名称只在解析后的源码拼写一致或被元变量捕获时视为相同。
@@ -391,6 +392,8 @@ for i = 0; j < n; i = i + 1 {
391392

392393
`const` 元变量捕获解析后的 MoonBit 常量。在表达式位置,它匹配 `Expr::Constant`;在 pattern 位置,它匹配 `Pattern::Constant`。
393394

395+
常量比较使用 parser AST 中的常量种类和保留的源码拼写;它不会进行类型检查,也不会归一化等值常量。例如,`1000` 和 `1_000` 不一定被视为同一个常量。
396+
394397
示例:
395398

396399
```yaml

docs/rule_spec.mbt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ let _embed_rulespec_md : String =
1919
#|
2020
#|Rules use YAML format. Every `shape` value is MoonBit surface syntax. The scanner
2121
#|matches parsed MoonBit expression structure and does not match raw text.
22-
#|Formatting and comments are not significant. Expression form, operators,
23-
#|literal values, labels, callee names, and argument structure are significant.
22+
#|Whitespace formatting and comments are not significant. Literal source spelling
23+
#|is an exception: constants are compared by their parser AST kind and preserved
24+
#|source spelling, not by normalized semantic value. Equivalent values such as
25+
#|`1000` and `1_000` therefore do not necessarily match. Expression form,
26+
#|operators, labels, callee names, and argument structure are also significant.
2427
#|Wildcards and declared metavariables modify these matching requirements as
2528
#|documented below.
2629
#|
@@ -134,13 +137,14 @@ let _embed_rulespec_md : String =
134137
#|Shapes are structural:
135138
#|
136139
#|- undeclared identifiers and labels match literally
137-
#|- constants match by value
140+
#|- constants match by parser AST kind and preserved source spelling; equivalent
141+
#| values such as `1000` and `1_000` do not necessarily match
138142
#|- operators match literally
139143
#|- call and method-call argument kinds, labels, order, and arity must match
140144
#|- type annotations and type names in matched syntax must match where present
141-
#|- source locations and formatting do not participate in matching; top-level
142-
#| documentation is an AST field and follows the `inside-toplevel` matching
143-
#| mode
145+
#|- source locations, comments, and whitespace formatting do not participate in
146+
#| matching; top-level documentation is an AST field and follows the
147+
#| `inside-toplevel` matching mode
144148
#|
145149
#|The scanner does not type-check shapes and does not resolve names semantically.
146150
#|For example, two imported names that refer to the same definition compare as
@@ -491,8 +495,9 @@ let _embed_rulespec_md : String =
491495
#|
492496
#|A `const` metavar captures a parsed MoonBit constant. In expression position,
493497
#|it matches `Expr::Constant`; in pattern position, it matches `Pattern::Constant`.
494-
#|It compares the parser AST constant kind and value only; it does not type-check
495-
#|or normalize equivalent values.
498+
#|It compares the parser AST constant kind and preserved source spelling; it does
499+
#|not type-check or normalize equivalent values. For example, `1000` and `1_000`
500+
#|do not necessarily compare as the same constant.
496501
#|
497502
#|Example:
498503
#|

e2etests/SCAN.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,26 @@ source:
225225
4 | render("raw")
226226
```
227227

228+
## Constant source spelling
229+
230+
Constant equality preserves the spelling stored in the parser AST instead of
231+
normalizing numeric values. A literal `1000` pattern therefore matches only the
232+
identically spelled call; the equivalent `1_000` call is omitted.
233+
234+
```mooncram
235+
$ cd "$TESTDIR"/.. && moonrun "$TESTDIR"/moongrep.wasm -- scan --output-json --pattern 'literal(1000)' testdata/constant-spelling/sample.mbt | sed -n 's/.*"matched_source":"\(.*\)","source_context".*/\1/p'
236+
literal(1000)
237+
```
238+
239+
The same comparison applies when a named `const` metavariable is repeated.
240+
Pairs with consistent spelling match, while `repeated(1000, 1_000)` does not.
241+
242+
```mooncram
243+
$ cd "$TESTDIR"/.. && moonrun "$TESTDIR"/moongrep.wasm -- scan --output-json --pattern 'repeated($(value:const), $(value:const))' testdata/constant-spelling/sample.mbt | sed -n 's/.*"matched_source":"\(.*\)","source_context".*/\1/p'
244+
repeated(1000, 1000)
245+
repeated(1_000, 1_000)
246+
```
247+
228248
## Rule filtering
229249

230250
Loading the prefilter rule directory runs both rules and reports their matches
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
///|
2+
fn constant_spellings {
3+
literal(1000)
4+
literal(1_000)
5+
repeated(1000, 1000)
6+
repeated(1_000, 1_000)
7+
repeated(1000, 1_000)
8+
}

0 commit comments

Comments
 (0)