From 8c2aecbf2cad503f27fa812d53070aac333a7f1c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 23 Jun 2023 17:23:08 -0700 Subject: [PATCH 1/6] Require variable names to be globally unique See https://github.com/unicode-org/message-format-wg/issues/310 --- spec/formatting.md | 56 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 6d956bdc1e..42a7e46afa 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -123,11 +123,15 @@ The resolution of a _text_ or _literal_ token MUST always succeed. To resolve the value of a _variable_, its _name_ is used to identify either a local variable, or a variable defined elsewhere. -If a local variable and an externally defined one use the same name, -the local variable takes precedence. -It is an error for a local variable definition to -refer to a local variable that's defined after it in the message. +It is an error for the right-hand side of a local variable declaration to +refer to a local variable that's declared after it in the message. + +Variable names are required to be globally unique. That is, +for any local variable declaration of the form `let $v = e`: +* It is an error if `v` is the left-hand side of a local variable declaration +that appears before `let $v = e` in the message. +* It is also an error if `v` is an externally defined variable. The resolution of a _variable_ MAY fail if no value is identified for its _name_. If this happens, an Unresolved Variable error MUST be emitted. @@ -230,6 +234,24 @@ rather than the _expression_ in the _selector_ or _pattern_. _Pattern selection_ is not supported for _fallback values_. +When there are multiple _declarations_ for the same _variable_, +the fallback string is formatted based on the _expression_ of +the first declaration of that _variable_. + +> For example, attempting to format the following message: +> +> ``` +> let $var = {|cart|} +> let $var = {|horse|} +> {The value is {$var}.} +> ``` +> +> would result in this formatted string representation: +> +> ``` +> The value is {|cart|}. +> ``` + ## Pattern Selection When a _message_ contains a _match_ construct with one or more _expressions_, @@ -704,6 +726,32 @@ These are divided into the following categories: > when * {The value is not one.} > ``` + - **Variable Redefinition errors** occur when + the left-hand side of a variable declaration is already defined, + either by a previous local variable declaration, + or by an external definition. + + > For example, attempting to format the following message + > must result in a Variable Redefinition error, + > because there is another declaration for `var` + > that textually precedes + > the declaration of `var` to be `{|horse|}`. + > + > ``` + > let $var = {|cart|} + > let $var = {|horse|} + > {The value is {$var}.} + > ``` + > + > Attempting to format the following message in a context + > where `var` is externally defined + > should also result in a Variable Redefinition error. + > + > ``` + > let $var = {|horse|} + > {The value is {$var}.} + > ``` + - **Unknown Function errors** occur when an _expression_ includes a reference to a function which cannot be resolved. From 05ba489ca73fbec5c16eb5330c5c6fb1da5e97c0 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 4 Jul 2023 19:42:12 -0700 Subject: [PATCH 2/6] Clarify definition of use-before-definition error --- spec/formatting.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 42a7e46afa..ad93caf87c 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -124,8 +124,22 @@ To resolve the value of a _variable_, its _name_ is used to identify either a local variable, or a variable defined elsewhere. -It is an error for the right-hand side of a local variable declaration to -refer to a local variable that's declared after it in the message. +When a _variable_is used as an _operand_, +the _name_ of this variable MUST either be: +1. The _name_ of a _variable_ of a _declaration_ that occurs before the +_operand_, or: +1. An externally defined variable. + +In case 1, the `entire` _declaration_ MUST appear before the _operand_. +For example, resolution of the following declaration should fail: + +``` +let $var = {$var} +``` + +because although a _variable_ with _name_ `var` occurs before +the expression `{$var}`, the entire declaration `let $var = {$var}` +does not occur before the expression `{$var}`. Variable names are required to be globally unique. That is, for any local variable declaration of the form `let $v = e`: From 8c8acad41657e0bafff620f2be7a56c54121004c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 4 Jul 2023 20:10:58 -0700 Subject: [PATCH 3/6] Rewrite the 'globally unique' property to use normative language --- spec/formatting.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index ad93caf87c..390c609cd4 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -141,11 +141,14 @@ because although a _variable_ with _name_ `var` occurs before the expression `{$var}`, the entire declaration `let $var = {$var}` does not occur before the expression `{$var}`. -Variable names are required to be globally unique. That is, -for any local variable declaration of the form `let $v = e`: -* It is an error if `v` is the left-hand side of a local variable declaration -that appears before `let $v = e` in the message. -* It is also an error if `v` is an externally defined variable. +Any _name_ MUST NOT appear as the _name_ of the _variable_ +in more than one _declaration_ within the same message. +If the _variable_ in a _declaration_ also appears +as the _variable_ in a previous _declaration_, +a Variable Redefinition error MUST be emitted. +If the _variable_ in a declaration is also +an externally defined variable, +a Formatting error MUST be emitted. The resolution of a _variable_ MAY fail if no value is identified for its _name_. If this happens, an Unresolved Variable error MUST be emitted. From dd3674d8bfd7fb2fb1656ac33f59518b6233b577 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 4 Jul 2023 20:17:27 -0700 Subject: [PATCH 4/6] Avoid normative language in examples --- spec/formatting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/formatting.md b/spec/formatting.md index 390c609cd4..724218cf54 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -749,7 +749,7 @@ These are divided into the following categories: or by an external definition. > For example, attempting to format the following message - > must result in a Variable Redefinition error, + > results in a Variable Redefinition error, > because there is another declaration for `var` > that textually precedes > the declaration of `var` to be `{|horse|}`. @@ -762,7 +762,7 @@ These are divided into the following categories: > > Attempting to format the following message in a context > where `var` is externally defined - > should also result in a Variable Redefinition error. + > also results in a Variable Redefinition error. > > ``` > let $var = {|horse|} From aebde67d503f9911c64789664216f01bd3cfa566 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 4 Jul 2023 20:18:01 -0700 Subject: [PATCH 5/6] Apply suggestions from code review 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 724218cf54..cbfa6b2b77 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -744,7 +744,7 @@ These are divided into the following categories: > ``` - **Variable Redefinition errors** occur when - the left-hand side of a variable declaration is already defined, +a `declaration` contains a `variable` that is already defined either by a previous local variable declaration, or by an external definition. From 828c748b0a4ca0db7cab661c12a2743558b6e824 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 4 Jul 2023 20:30:42 -0700 Subject: [PATCH 6/6] Clarify fallback string when an external variable is redefined, and add an example of that --- spec/formatting.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/spec/formatting.md b/spec/formatting.md index cbfa6b2b77..16072adedd 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -252,8 +252,10 @@ rather than the _expression_ in the _selector_ or _pattern_. _Pattern selection_ is not supported for _fallback values_. When there are multiple _declarations_ for the same _variable_, +or when a _declaration_ redefines a _variable_ +that is externally defined, the fallback string is formatted based on the _expression_ of -the first declaration of that _variable_. +the first local declaration of that _variable_. > For example, attempting to format the following message: > @@ -268,6 +270,19 @@ the first declaration of that _variable_. > ``` > The value is {|cart|}. > ``` +> +> Also, attempting to format the following message: +> ``` +> let $var = {|cart|} +> {The value is {$var}.} +> ``` +> +> in a context where `var` is externally defined +> would result in the same formatted string representation: +> +> ``` +> The value is {|cart|}. +> ``` ## Pattern Selection