From 5aa988b44e61422c80c04137e94db914ed117404 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 May 2023 15:08:31 -0700 Subject: [PATCH 1/9] Clarifications to pattern selection * State up front that the catch-all key `*` is never passed to the implementation-defined key-comparison method * Clarify the relationship between selector length and key length * Clarify the type signature for `SortVariants` * Fix typo --- spec/formatting.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 8d6a540876..46cc827848 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -27,11 +27,14 @@ the _pattern_ of one of the _variants_ must be selected for formatting. When a message has a single _selector_, an implementation-defined method compares each key to the _selector_ and determines which of the keys match, and in what order of preference. -A catch-all key will always match, but is always the least preferred choice. -During selection, the _variant_ with the best-matching key is selected. +The list of keys passed to this implementation-defined method +does not include the catch-all key `*`. +The formatter treats the catch-all key `*` +as a match for any _selector_, +but with the lowest possible preference. In a message with more than one _selector_, -each _variant_ also has a corresponding number of keys. +the number of keys in each _variant_ equals the number of _selectors_. These correspond to _selectors_ by position. The same implementation-defined method as above is used to compare the corresponding key of each _variant_ to its _selector_, @@ -134,7 +137,7 @@ Finally, sort the list of variants `vars` and select the _pattern_: The method SortVariants is determined by the implementation. It takes as an argument a `sortable` list of (integer, _variant_) tuples, which it modifies in place using some stable sorting algorithm. -The method does not return anything. +The method does not return a value: `sortable` is its out-parameter. The list is sorted according to the tuple's first integer element, such that a lower number is sorted before a higher one, and entries that have the same number retain their order. @@ -221,7 +224,7 @@ when * * {Otherwise} Presuming a more powerful implementation which supports selection on numerical values, and provides a `:plural` function that matches keys by their exact value as well as their plural category (preferring the former, if possible), -and an Enligh-language formatting context in which +and an English-language formatting context in which the variable reference `$count` resolves to the number `1`, pattern selection proceeds as follows for this message: From e2c61e261c76ab6338c4c2039fbb09a6f7e0a6bc Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 23 May 2023 15:28:34 -0700 Subject: [PATCH 2/9] Remove reference to "the formatter" in description of catch-all matching Co-authored-by: Eemeli Aro --- spec/formatting.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 46cc827848..e0f3c5555f 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -29,8 +29,7 @@ an implementation-defined method compares each key to the _selector_ and determines which of the keys match, and in what order of preference. The list of keys passed to this implementation-defined method does not include the catch-all key `*`. -The formatter treats the catch-all key `*` -as a match for any _selector_, +The catch-all key `*` is treated as a match for any _selector_, but with the lowest possible preference. In a message with more than one _selector_, From 919e1d4965f5ac803be3ab2223161464d9d56f9f Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 23 May 2023 15:39:15 -0700 Subject: [PATCH 3/9] Change "decoded" to "resolved" for keys Change references to "the decoded value of a key" to "the resolved value of a key", and clarify that key resolution is the same as literal resolution --- spec/formatting.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index e0f3c5555f..11ccda381b 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -46,6 +46,12 @@ with earlier _selectors_ having higher priority than later ones. Finally, the highest-sorted _variant_ is selected. This selection method is defined in more detail below. +In these definitions, "the resolved value of a key" +refers to the result of the process +described in the "Literal Resolution" section. +(Key resolution is the same as literal resolution +because the methods below do not apply resolution +to the catch-all key '*'.) An implementation MAY use any pattern selection method, as long as its observable behaviour matches the results of the method defined here. @@ -76,7 +82,7 @@ Next, using `res`, resolve the preferential order for all message keys: 1. For each _variant_ `var` of the message: 1. Let `key` be the `var` key at position `i`. 1. If `key` is not the catch-all key `'*'`: - 1. Let `ks` be the decoded value of `key`. + 1. Let `ks` be the resolved value of `key`. 1. Append `ks` as the last element of the list `keys`. 1. Let `rv` be the resolved value at index `i` of `res`. 1. Let `matches` be the result of calling the method MatchSelectorKeys(`rv`, `keys`) @@ -100,7 +106,7 @@ filter the list of _variants_ to the ones that match with some preference: 1. Let `key` be the `var` key at position `i`. 1. If `key` is the catch-all key `'*'`: 1. Continue the inner loop on `pref`. - 1. Let `ks` be the decoded value of `key`. + 1. Let `ks` be the resolved value of `key`. 1. Let `matches` be the list of strings at index `i` of `pref`. 1. If `matches` includes `ks`: 1. Continue the inner loop on `pref`. @@ -125,7 +131,7 @@ Finally, sort the list of variants `vars` and select the _pattern_: 1. Let `matchpref` be an integer with the value `minpref`. 1. Let `key` be the `tuple` _variant_ key at position `i`. 1. If `key` is not the catch-all key `'*'`: - 1. Let `ks` be the decoded value of `key`. + 1. Let `ks` be the resolved value of `key`. 1. Let `matchpref` be the integer position of `ks` in `matches`. 1. Set the `tuple` integer value as `matchpref`. 1. Call the method SortVariants(`sortable`). From 81efa3ee8ee9bd3818902552c951113d61c4fa59 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 23 May 2023 22:59:49 -0700 Subject: [PATCH 4/9] Clarify the relationship between key resolution and literal resolution Co-authored-by: Eemeli Aro --- spec/formatting.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/formatting.md b/spec/formatting.md index 11ccda381b..ebfef35a75 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -82,6 +82,7 @@ Next, using `res`, resolve the preferential order for all message keys: 1. For each _variant_ `var` of the message: 1. Let `key` be the `var` key at position `i`. 1. If `key` is not the catch-all key `'*'`: + 1. Assert that `key` is a _literal_. 1. Let `ks` be the resolved value of `key`. 1. Append `ks` as the last element of the list `keys`. 1. Let `rv` be the resolved value at index `i` of `res`. From ade76a3657a588f12e8b9a53d549129fbf25e07d Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 23 May 2023 23:02:50 -0700 Subject: [PATCH 5/9] Clarify the relationship between key resolution and literal resolution in all instances * Also remove up-front text explaining key resolution --- spec/formatting.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index ebfef35a75..5758bc6318 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -46,12 +46,6 @@ with earlier _selectors_ having higher priority than later ones. Finally, the highest-sorted _variant_ is selected. This selection method is defined in more detail below. -In these definitions, "the resolved value of a key" -refers to the result of the process -described in the "Literal Resolution" section. -(Key resolution is the same as literal resolution -because the methods below do not apply resolution -to the catch-all key '*'.) An implementation MAY use any pattern selection method, as long as its observable behaviour matches the results of the method defined here. @@ -107,6 +101,7 @@ filter the list of _variants_ to the ones that match with some preference: 1. Let `key` be the `var` key at position `i`. 1. If `key` is the catch-all key `'*'`: 1. Continue the inner loop on `pref`. + 1. Assert that `key` is a _literal_. 1. Let `ks` be the resolved value of `key`. 1. Let `matches` be the list of strings at index `i` of `pref`. 1. If `matches` includes `ks`: @@ -132,6 +127,7 @@ Finally, sort the list of variants `vars` and select the _pattern_: 1. Let `matchpref` be an integer with the value `minpref`. 1. Let `key` be the `tuple` _variant_ key at position `i`. 1. If `key` is not the catch-all key `'*'`: + 1. Assert that `key` is a _literal_. 1. Let `ks` be the resolved value of `key`. 1. Let `matchpref` be the integer position of `ks` in `matches`. 1. Set the `tuple` integer value as `matchpref`. From 3cd09148db3f2672791d3a142f988b5ebc025deb Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 30 May 2023 18:22:12 -0700 Subject: [PATCH 6/9] Normative language for required number of keys in variants Co-authored-by: Addison Phillips --- spec/formatting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/formatting.md b/spec/formatting.md index 5758bc6318..94e5ed4086 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -33,7 +33,7 @@ The catch-all key `*` is treated as a match for any _selector_, but with the lowest possible preference. In a message with more than one _selector_, -the number of keys in each _variant_ equals the number of _selectors_. +the number of keys in each _variant_ **_must_** equal the number of _selectors_. These correspond to _selectors_ by position. The same implementation-defined method as above is used to compare the corresponding key of each _variant_ to its _selector_, From f08b9b60a94321d17fb82b8e16d7ae3b63ae770a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 30 May 2023 18:51:31 -0700 Subject: [PATCH 7/9] Rewrite the call to `SortVariants` In the "Sort Variants" definition, re-specify the implementation-dependent `SortVariants` so as not to constraint whether it modifies the list in-place or returns a new list --- spec/formatting.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 94e5ed4086..6121f360cb 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -131,18 +131,22 @@ Finally, sort the list of variants `vars` and select the _pattern_: 1. Let `ks` be the resolved value of `key`. 1. Let `matchpref` be the integer position of `ks` in `matches`. 1. Set the `tuple` integer value as `matchpref`. - 1. Call the method SortVariants(`sortable`). + 1. Set `sortable` to be `SortVariants(sortable)`. 1. Set `i` to be `i` - 1. 1. Let `var` be the _variant_ element of the first element of `sortable`. 1. Select the _pattern_ of `var`. -The method SortVariants is determined by the implementation. -It takes as an argument a `sortable` list of (integer, _variant_) tuples, -which it modifies in place using some stable sorting algorithm. -The method does not return a value: `sortable` is its out-parameter. -The list is sorted according to the tuple's first integer element, -such that a lower number is sorted before a higher one, -and entries that have the same number retain their order. +`SortVariants` is a method whose single argument is +a list of (integer, _variant_) tuples. +It returns a list of (integer, _variant_) tuples. +Any implementation of `SortVariants` is acceptable +as long as it satisfies the following requirements: +1. Let `sortable` be an arbitrary list of (integer, _variant_) tuples. +1. Let `sorted` be `SortVariants(sortable)`. +1. `sorted` is the result of sorting `sortable` using the following comparator: + 1. `(i1, v1)` <= `(i2, v2)` if and only if `i1 <= i2`. +1. The sort is stable (pairs of tuples from `sortable` that are equal + in their first element have the same relative order in `sorted`). ### Examples From 04bc82dba09a2d30ddb042481f1da55ae375adf0 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 30 May 2023 23:56:14 -0700 Subject: [PATCH 8/9] Follow style for describing method return values Co-authored-by: Eemeli Aro --- spec/formatting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/formatting.md b/spec/formatting.md index 6121f360cb..fa2564c1ed 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -131,7 +131,7 @@ Finally, sort the list of variants `vars` and select the _pattern_: 1. Let `ks` be the resolved value of `key`. 1. Let `matchpref` be the integer position of `ks` in `matches`. 1. Set the `tuple` integer value as `matchpref`. - 1. Set `sortable` to be `SortVariants(sortable)`. + 1. Set `sortable` to be the result of calling the method `SortVariants(sortable)`. 1. Set `i` to be `i` - 1. 1. Let `var` be the _variant_ element of the first element of `sortable`. 1. Select the _pattern_ of `var`. From 8668af2135feba3388a4dec86a64a45a01dd423a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 30 May 2023 23:56:39 -0700 Subject: [PATCH 9/9] Add newline Co-authored-by: Eemeli Aro --- spec/formatting.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/formatting.md b/spec/formatting.md index fa2564c1ed..8274e98af6 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -141,6 +141,7 @@ a list of (integer, _variant_) tuples. It returns a list of (integer, _variant_) tuples. Any implementation of `SortVariants` is acceptable as long as it satisfies the following requirements: + 1. Let `sortable` be an arbitrary list of (integer, _variant_) tuples. 1. Let `sorted` be `SortVariants(sortable)`. 1. `sorted` is the result of sorting `sortable` using the following comparator: