Skip to content
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
eff3bac
Implement the simplified pattern selection algorithm in the spec (#898)
catamorphism Jun 10, 2025
7738bfc
Use sentence case for SelectorsMatch and SelectorsCompare
catamorphism Jun 16, 2025
ee00735
Make notation for match/compare consistent
catamorphism Jun 16, 2025
4d37d2d
Add missing `let`s
catamorphism Jun 16, 2025
0d800ab
Rephrase to use early return
catamorphism Jun 16, 2025
2aab6a5
Move pattern selection examples to an appendix
catamorphism Jun 16, 2025
4023bae
Fix internal link
catamorphism Jun 16, 2025
fee68c6
Fix method names in examples
catamorphism Jun 16, 2025
8db5cb6
Fix assertions; fix method names in function specs
catamorphism Jun 16, 2025
d0597e6
Replace references to selectKeys with match/compare
catamorphism Jun 16, 2025
5e92447
Update spec/formatting.md
catamorphism Jun 17, 2025
99738a6
Replace assertions with prose
catamorphism Jun 17, 2025
68c8d2e
Update spec/formatting.md
catamorphism Jun 17, 2025
23a5c4f
Rewrite 'Operations on Resolved Values' section
catamorphism Jun 17, 2025
2f20744
Fix markup
catamorphism Jun 17, 2025
4b577a6
Move examples to appendices.md
catamorphism Jun 17, 2025
68311a1
Add NormalizeKey operation; clean up markup errors that I missed earlier
catamorphism Jun 17, 2025
fd7bd90
Update spec for :test:select function
catamorphism Jun 17, 2025
898a714
Rename Compare to BetterThan and make it and SelectorsCompare return …
catamorphism Jun 17, 2025
73397d3
Update spec/formatting.md
catamorphism Jun 19, 2025
2659257
Update spec/formatting.md
catamorphism Jun 19, 2025
14e045f
Update spec/formatting.md
catamorphism Jun 19, 2025
0bf3af6
Update spec/formatting.md
catamorphism Jun 19, 2025
729da2c
Update spec/formatting.md
catamorphism Jun 19, 2025
aa9603b
Update spec/formatting.md
catamorphism Jun 19, 2025
eb2d673
Update spec/formatting.md
catamorphism Jun 19, 2025
6f5a39d
Update examples for spec changes
catamorphism Jun 19, 2025
d419a55
Fix typo
catamorphism Jun 19, 2025
fd95a09
Update spec/formatting.md
catamorphism Jun 23, 2025
6cfd863
Update spec/formatting.md
catamorphism Jun 23, 2025
33b8b57
Update spec/formatting.md
catamorphism Jun 23, 2025
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
196 changes: 196 additions & 0 deletions spec/appendices.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,202 @@ fingerprinting, and other types of bad behavior.
Any installed code needs to be appropriately sandboxed.
In addition, end-users need to be aware of the risks involved.

### Non-normative Examples

#### Pattern Selection Examples

##### Selection Example 1

Presuming a minimal implementation which only supports `:string` _function_
which matches keys by using string comparison,
and a formatting context in which
the variable reference `$foo` resolves to the string `'foo'` and
the variable reference `$bar` resolves to the string `'bar'`,
pattern selection proceeds as follows for this message:

```
.input {$foo :string}
.input {$bar :string}
.match $foo $bar
bar bar {{All bar}}
foo foo {{All foo}}
* * {{Otherwise}}
```

1. Each selector is resolved, yielding the list `res` = `{foo, bar}`.
2. `bestVariant` is set to `UNSET`.
3. `keys` is set to `{bar, bar}`.
4. `match` is set to SelectorsMatch(`{foo, bar}`, `{bar, bar}`).
The result of SelectorsMatch(`{foo, bar}`, `{bar, bar}`) is
determined as follows:
1. `result` is set to true.
1. `i` is set to 0.
1. `k` is set to the string `bar`.
1. `sel` is set to a resolved value corresponding to the string `foo`.
1. Match(`sel`, `'bar'`) is false.
1. The result of SelectorsMatch(`{foo, bar}`, `{bar, bar}`) is false.
Thus, `match` is set to false.
5. `keys` is set to `{foo, foo}`.
6. `match` is set to SelectorsMatch(`{foo, bar}`, `{foo, foo}`).
The result of SelectorsMatch(`{foo, bar}`, `{foo, foo}`) is
determined as follows:
1. `result` is set to true.
1. `i` is set to 0.
1. `k` is set to the string `foo`.
1. `sel` is set to a resolved value corresponding to the string `foo`.
1. Match(`sel`, `'foo'`) is true.
1. `i` is set to 1.
1. `k` is set to the string `foo`.
1. `sel` is set to a resolved value corresponding to the string `bar`.
1. Match(`sel`, `'bar'`) is false.
1. The result of SelectorsMatch(`{foo, bar}`, `{foo, foo}`) is false.
7. `keys` is set to `* *`.
8. The result of SelectorsMatch(`{foo, bar}`, `{*, *}`) is
determined as follows:
1. `result` is set to true.
1. `i` is set to 0.
1. `i` is set to 1.
1. `i` is set to 2.
1. The result of SelectorsMatch(`{foo, bar}`, `{*, *}`) is true.
9. `bestVariant` is set to the variant `* * {{Otherwise}}`
10. The pattern `Otherwise` is selected.

##### Selection Example 2

Alternatively, with the same implementation and formatting context as in Example 1,
pattern selection would proceed as follows for this message:

```
.input {$foo :string}
.input {$bar :string}
.match $foo $bar
* bar {{Any and bar}}
foo * {{Foo and any}}
foo bar {{Foo and bar}}
* * {{Otherwise}}
```

1. Each selector is resolved, yielding the list `res` = `{foo, bar}`.
2. `bestVariant` is set to `UNSET`.
3. `keys` is set to `{*, bar}`.
4. `match` is set to SelectorsMatch(`{foo, bar}`, `{*, bar}`)
The result of SelectorsMatch(`{foo, bar}`, `{*, bar}`) is
determined as follows:
1. `result` is set to true.
2. `i` is set to 0.
3. `i` is set to 1.
4. `k` is set to the string `bar`.
5. `sel` is set to a resolved value corresponding to the string `bar`.
6. Match(`sel`, `'bar'`) is true.
7. `i` is set to 2.
1. The result of SelectorsMatch(`{foo, bar}`, `{*, bar}`) is true.
5. `bestVariant` is set to the variant `* bar {{Any and bar}}`.
6. `keys` is set to `{foo, *}`.
7. `match` is set to SelectorsMatch(`{foo, bar}`, `{foo, *}`).
The result of SelectorsMatch(`{foo, bar}`, `{foo, *}`) is
determined as follows:
1. `result` is set to true.
2. `i` is set to 0.
3. `k` is set to the string `foo`.
4. `sel` is set to a resolved value corresponding to the string `foo`.
5. Match(`sel`, `'foo'`) is true.
6. `i` is set to 1.
7. `i` is set to 2.
8. The result of SelectorsMatch(`{foo, bar}`, `{foo, *}`) is true.
8. `bestVariantKeys` is set to `{*, bar}`.
9. SelectorsCompare(`{foo, bar}`, `{foo, *}`, `{*, bar}`) is
determined as follows:
1. `result` is set to false.
1. `i` is set to 0.
1. `key1` is set to `foo`.
1. `key2` is set to `'*'`
1. The result of SelectorsCompare(`{foo, bar}`, `{foo, *}`, `{*, bar}`) is true.
10. `bestVariant` is set to `foo * {{Foo and any}}`.
11. `keys` is set to `{foo, bar}`.
12. `match` is set to SelectorsMatch(`{foo, bar}`, `{foo, bar}`).
1. `match` is true (details elided)
13. `bestVariantKeys` is set to `{foo, *}`.
14. SelectorsCompare(`{foo, bar}`, `{foo, bar}`, `{foo, *}`) is
determined as follows:
1. `result` is set to false.
1. `i` is set to 0.
1. `key1` is set to `foo`.
1. `key2` is set to `foo`.
1. `k1` is set to `foo`.
1. `k2` is set to `foo`.
1. `sel` is set to a resolved value corresponding to `foo`.
1. `i` is set to 1.
1. `key1` is set to `bar`.
1. `key2` is set to `*`.
1. The result of SelectorsCompare(`{foo, bar}`, `{foo, bar}`, `{foo, *}`)
is true.
15. `bestVariant` is set to `foo bar {{Foo and bar}}`.
16. `keys` is set to `* *`.
17. `match` is set to true (details elided).
18. `bestVariantKeys` is set to `foo bar`.
19. SelectorsCompare(`{foo, bar}`, `{*, *}`, `{foo, bar}`} is false
(details elided).

The pattern `{{Foo and bar}}` is selected.

##### Selection Example 3

A more-complex example is the matching found in selection APIs
such as ICU's `PluralFormat`.
Suppose that this API is represented here by the function `:number`.
This `:number` function can match a given numeric value to a specific number _literal_
and **_also_** to a plural category (`zero`, `one`, `two`, `few`, `many`, `other`)
according to locale rules defined in CLDR.

Given a variable reference `$count` whose value resolves to the number `1`
and an `en` (English) locale,
the pattern selection proceeds as follows for this message:

```
.input {$count :number}
.match $count
one {{Category match for {$count}}}
1 {{Exact match for {$count}}}
* {{Other match for {$count}}}
```

1. Each selector is resolved, yielding the list `{1}`.
1. `bestVariant` is set to `UNSET`.
1. `keys` is set to `{one}`.
1. `match` is set to SelectorsMatch(`{1}`, `{one}`).
The result of SelectorsMatch(`{1}`, `{one}`) is
determined as follows:
1. `result` is set to true.
1. `i` is set to 0.
1. `k` is set to `one`.
1. `sel` is set to `1`.
1. Match(`sel`, `one`) is true.
1. `i` is set to 1.
1. The result of SelectorsMatch(`{1}`, `{one}`) is true.
1. `bestVariant` is set to `one {{Category match for {$count}}}`.
1. `keys` is set to `1`.
1. `match` is set to SelectorsMatch(`{1}`, `{one}`).
1. The details are the same as the previous case,
as Match(`sel`, `1`) is also true.
1. `bestVariantKeys` is set to `{one}`.
1. SelectorsCompare(`{1}`, `{1}`, `{one}`) is determined as follows:
1. `result` is set to false.
1. `i` is set to 0.
1. `key1` is set to `1`.
1. `key2` is set to `one`.
1. `k1` is set to `1`.
1. `k2` is set to `one`.
1. `sel` is set to `1`.
1. `result` is set to BetterThan(`sel`, `1`, `one`), which is true.
1. NOTE: The specification of the `:number` selector function
states that the exact match `1` is a better match than
the category match `one`.
1. `bestVariant` is set to `1 {{Exact match for {$count}}}`.
1. `keys` is set to `*`
1. Details elided; since `*` is the catch-all key,
BetterThan(`{1}`, `{1}`, `{*}`) is false.
1. The pattern `{{Exact match for {$count}}}` is selected.

### Acknowledgements

Special thanks to the following people for their contributions to making the Unicode MessageFormat Standard.
Expand Down
Loading