diff --git a/spec/errors.md b/spec/errors.md index a625b1c4e1..5782622b2e 100644 --- a/spec/errors.md +++ b/spec/errors.md @@ -269,7 +269,7 @@ a reference to a function which cannot be resolved. ### Bad Selector A **_Bad Selector_** error occurs when a message includes a _selector_ -with a resolved value which does not support selection. +with a _resolved value_ which does not support selection. > For example, attempting to format this message > would result in a _Bad Selector_ error: @@ -283,10 +283,10 @@ with a resolved value which does not support selection. ## Message Function Errors A **_Message Function Error_** is any error that occurs -when calling a message function implementation +when calling a _function handler_ or which depends on validation associated with a specific function. -Implementations SHOULD provide a way for _functions_ to emit +Implementations SHOULD provide a way for _function handlers_ to emit (or cause to be emitted) any of the types of error defined in this section. Implementations MAY also provide implementation-defined _Message Function Error_ types. @@ -300,7 +300,7 @@ Implementations MAY also provide implementation-defined _Message Function Error_ > 3. Uses a `:get` message function which requires its argument to be an object and > an option `field` to be provided with a string value. > -> The exact type of _Message Function Error_ is determined by the message function implementation. +> The exact type of _Message Function Error_ is determined by the _function handler_. > > ``` > Hello, {horse :get field=name}! diff --git a/spec/formatting.md b/spec/formatting.md index f048975659..27495fb01e 100644 --- a/spec/formatting.md +++ b/spec/formatting.md @@ -16,7 +16,8 @@ The formatting of a _message_ is defined by the following operations: For a message with no _selectors_, this is simple as there is only one _pattern_. With _selectors_, this will depend on their resolution. -- **_Formatting_** takes the resolved values of the selected _pattern_, +- **_Formatting_** takes the _resolved values_ of + the _text_ and _placeholder_ parts of the selected _pattern_, and produces the formatted result for the _message_. Depending on the implementation, this result could be a single concatenated string, an array of objects, an attributed string, or some other locally appropriate data type. @@ -25,7 +26,7 @@ The formatting of a _message_ is defined by the following operations: with reference to the current _formatting context_. This can include multiple steps, such as looking up the value of a variable and calling formatting functions. - The form of the resolved value is implementation defined and the + The form of the _resolved value_ is implementation defined and the value might not be evaluated or formatted yet. However, it needs to be "formattable", i.e. it contains everything required by the eventual formatting. @@ -40,7 +41,7 @@ as long as the final _formatting_ result is made available to users and the observable behavior of the _formatting_ matches that described here. _Attributes_ MUST NOT have any effect on the formatted output of a _message_, -nor be made available to function implementations. +nor be made available to _function handlers_. > [!IMPORTANT] > @@ -77,50 +78,92 @@ At a minimum, it includes: This is often determined by a user-provided argument of a formatting function call. - The _function registry_, - providing the implementations of the functions referred to by message _functions_. + providing the _function handlers_ of the functions referred to by message _functions_. - Optionally, a fallback string to use for the message if it is not _valid_. Implementations MAY include additional fields in their _formatting context_. -## Expression and Markup Resolution +## Resolved Values -_Expressions_ are used in _declarations_ and _patterns_. -_Markup_ is only used in _patterns_. +A **_resolved value_** is the result of resolving a _text_, _literal_, _variable_, _expression_, or _markup_. +The _resolved value_ is determined using the _formatting context_. +The form of the _resolved value_ is implementation-defined. -In a _declaration_, the resolved value of the _expression_ is bound to a _variable_, -which is available for use by later _expressions_. -Since a _variable_ can be referenced in different ways later, -implementations SHOULD NOT immediately fully format the value for output. +In a _declaration_, the _resolved value_ of an _expression_ is bound to a _variable_, +which makes it available for use in later _expressions_ and _markup_ _options_. + +> For example, in +> ``` +> .input {$a :number minimumFractionDigits=3} +> .local $b = {$a :integer notation=compact} +> .match $a +> 0 {{The value is zero.}} +> * {{In compact form, the value {$a} is rendered as {$b}.}} +> ``` +> the _resolved value_ bound to `$a` is used as the _operand_ +> of the `:integer` _function_ when resolving the value of the _variable_ `$b`, +> as a _selector_ in the `.match` statement, +> as well as for formatting the _placeholder_ `{$a}`. In an _input-declaration_, the _variable_ operand of the _variable-expression_ identifies not only the name of the external input value, -but also the _variable_ to which the resolved value of the _variable-expression_ is bound. +but also the _variable_ to which the _resolved value_ of the _variable-expression_ is bound. -In a _pattern_, the resolved value of an _expression_ or _markup_ is used in its _formatting_. +In a _pattern_, the _resolved value_ of an _expression_ or _markup_ is used in its _formatting_. -The form that resolved values take is implementation-dependent, +The form that _resolved values_ take is implementation-dependent, and different implementations MAY choose to perform different levels of resolution. -> For example, the resolved value of the _expression_ `{|0.40| :number style=percent}` -> could be an object such as +> While this specification does not require it, +> a _resolved value_ could be implemented by requiring each _function handler_ to +> return a value matching the following interface: > +> ```ts +> interface MessageValue { +> formatToString(): string +> formatToX(): X // where X is an implementation-defined type +> getValue(): unknown +> resolvedOptions(): { [key: string]: MessageValue } +> selectKeys(keys: string[]): string[] +> } > ``` -> { value: Number('0.40'), -> formatter: NumberFormat(locale, { style: 'percent' }) } -> ``` > -> Alternatively, it could be an instance of an ICU4J `FormattedNumber`, -> or some other locally appropriate value. +> With this approach: +> - An _expression_ could be used as a _placeholder_ if +> calling the `formatToString()` or `formatToX()` method of its _resolved value_ +> did not emit an error. +> - A _variable_ could be used as a _selector_ if +> calling the `selectKeys(keys)` method of its _resolved value_ +> did not emit an error. +> - Using a _variable_, the _resolved value_ of an _expression_ +> could be used as an _operand_ or _option_ value if +> calling the `getValue()` method of its _resolved value_ did not emit an error. +> In this use case, the `resolvedOptions()` method could also +> provide a set of option values that could be taken into account by the called function. +> +> Extensions of the base `MessageValue` interface could be provided for different data types, +> such as numbers or strings, +> for which the `unknown` return type of `getValue()` and +> the generic `MessageValue` type used in `resolvedOptions()` +> could be narrowed appropriately. +> An implementation could also allow `MessageValue` values to be passed in as input variables, +> or automatically wrap each variable as a `MessageValue` to provide a uniform interface +> for custom functions. + +## Expression and Markup Resolution + +_Expressions_ are used in _declarations_ and _patterns_. +_Markup_ is only used in _patterns_. Depending on the presence or absence of a _variable_ or _literal_ operand and a _function_, -the resolved value of the _expression_ is determined as follows: +the _resolved value_ of the _expression_ is determined as follows: If the _expression_ contains a _function_, -its resolved value is defined by _function resolution_. +its _resolved value_ is defined by _function resolution_. Else, if the _expression_ consists of a _variable_, -its resolved value is defined by _variable resolution_. +its _resolved value_ is defined by _variable resolution_. An implementation MAY perform additional processing when resolving the value of an _expression_ that consists only of a _variable_. @@ -139,9 +182,9 @@ that consists only of a _variable_. > the pattern included the function `:datetime` with some set of default options. Else, the _expression_ consists of a _literal_. -Its resolved value is defined by _literal resolution_. +Its _resolved value_ is defined by _literal resolution_. -> **Note** +> [!NOTE] > This means that a _literal_ value with no _function_ > is always treated as a string. > To represent values that are not strings as a _literal_, @@ -156,25 +199,40 @@ Its resolved value is defined by _literal resolution_. ### Literal Resolution -The resolved value of a _text_ or a _literal_ is +The _resolved value_ of a _text_ or a _literal_ contains the character sequence of the _text_ or _literal_ after any character escape has been converted to the escaped character. When a _literal_ is used as an _operand_ or on the right-hand side of an _option_, -the formatting function MUST treat its resolved value the same +the formatting function MUST treat its _resolved value_ the same whether its value was originally a _quoted literal_ or an _unquoted literal_. > For example, > the _option_ `foo=42` and the _option_ `foo=|42|` are treated as identical. -The resolution of a _text_ or _literal_ MUST resolve to a string. + +> For example, in a JavaScript formatter +> the _resolved value_ of a _text_ or a _literal_ could have the following implementation: +> +> ```ts +> class MessageLiteral implements MessageValue { +> constructor(value: string) { +> this.formatToString = () => value; +> this.getValue = () => value; +> } +> resolvedOptions: () => ({}); +> selectKeys(_keys: string[]) { +> throw Error("Selection on unannotated literals is not supported"); +> } +> } +> ``` ### Variable Resolution To resolve the value of a _variable_, its _name_ is used to identify either a local variable or an input variable. -If a _declaration_ exists for the _variable_, its resolved value is used. +If a _declaration_ exists for the _variable_, its _resolved value_ is used. Otherwise, the _variable_ is an implicit reference to an input value, and its value is looked up from the _formatting context_ _input mapping_. @@ -191,8 +249,8 @@ the following steps are taken: 1. If the _expression_ includes an _operand_, resolve its value. If this fails, use a _fallback value_ for the _expression_. 2. Resolve the _identifier_ of the _function_ and, based on the starting sigil, - find the appropriate function implementation to call. - If the implementation cannot find the function, + find the appropriate _function handler_ to call. + If the implementation cannot find the _function handler_, or if the _identifier_ includes a _namespace_ that the implementation does not support, emit an _Unknown Function_ error and use a _fallback value_ for the _expression_. @@ -202,108 +260,63 @@ the following steps are taken: 3. Perform _option resolution_. -4. Call the function implementation with the following arguments: +4. Call the _function handler_ with the following arguments: - The current _locale_. - The resolved mapping of _options_. - - If the _expression_ includes an _operand_, its resolved value. + - If the _expression_ includes an _operand_, its _resolved value_. The form that resolved _operand_ and _option_ values take is implementation-defined. - A _declaration_ binds the resolved value of an _expression_ - to a _variable_. - Thus, the result of one _function_ is potentially the _operand_ - of another _function_, - or the value of one of the _options_ for another function. - For example, in - ``` - .input {$n :number minimumIntegerDigits=3} - .local $n1 = {$n :number maximumFractionDigits=3} - ``` - the value bound to `$n` is the - resolved value used as the _operand_ - of the `:number` _function_ - when resolving the value of the _variable_ `$n1`. - - Implementations that provide a means for defining custom functions - SHOULD provide a means for function implementations - to return values that contain enough information - (e.g. a representation of - the resolved _operand_ and _option_ values - that the function was called with) - to be used as arguments to subsequent calls - to the function implementations. - For example, an implementation might define an interface that allows custom function implementation. - Such an interface SHOULD define an implementation-specific - argument type `T` and return type `U` - for implementations of functions - such that `U` can be coerced to `T`. - Implementations of a _function_ SHOULD emit a - _Bad Operand_ error for _operands_ whose resolved value - or type is not supported. - -> [!NOTE] -> The behavior of the previous example is -> currently implementation-dependent. Supposing that -> the external input variable `n` is bound to the string `"1"`, -> and that the implementation formats to a string, -> the formatted result of the following message: -> -> ``` -> .input {$n :number minimumIntegerDigits=3} -> .local $n1 = {$n :number maximumFractionDigits=3} -> {{What is the value of: {$n1}}} -> ``` -> -> is currently implementation-dependent. -> Depending on whether the options are preserved -> between the resolution of the first `:number` _function_ -> and the resolution of the second `:number` _function_, -> a conformant implementation -> could produce either "001.000" or "1.000" -> -> Each function **specification** MAY have -> its own rules to preserve some options in the returned structure -> and discard others. -> In instances where a function specification does not determine whether an option is preserved or discarded, -> each function **implementation** of that specification MAY have -> its own rules to preserve some options in the returned structure -> and discard others. -> - -> [!NOTE] -> During the Technical Preview, -> feedback on how the registry describes -> the flow of _resolved values_ and _options_ -> from one _function_ to another, -> and on what requirements this specification should impose, -> is highly desired. - - An implementation MAY pass additional arguments to the function, + An implementation MAY pass additional arguments to the _function handler_, as long as reasonable precautions are taken to keep the function interface simple and minimal, and avoid introducing potential security vulnerabilities. - An implementation MAY define its own functions. - An implementation MAY allow custom functions to be defined by users. - - Function access to the _formatting context_ MUST be minimal and read-only, - and execution time SHOULD be limited. - - Implementation-defined _functions_ SHOULD use an implementation-defined _namespace_. - 5. If the call succeeds, resolve the value of the _expression_ as the result of that function call. If the call fails or does not return a valid value, emit the appropriate _Message Function Error_ for the failure. - Implementations MAY provide a mechanism for the _function_ to provide + Implementations MAY provide a mechanism for the _function handler_ to provide additional detail about internal failures. Specifically, if the cause of the failure was that the datatype, value, or format of the _operand_ did not match that expected by the _function_, - the _function_ might cause a _Bad Operand_ error to be emitted. + the _function_ SHOULD cause a _Bad Operand_ error to be emitted. - In all failure cases, use the _fallback value_ for the _expression_ as the resolved value. + In all failure cases, use the _fallback value_ for the _expression_ as its _resolved value_. + +#### Function Handler + +A **_function handler_** is an implementation-defined process +such as a function or method +which accepts a set of arguments and returns a _resolved value_. +A _function handler_ is required to resolve a _function_. + +An implementation MAY define its own functions and their handlers. +An implementation MAY allow custom functions to be defined by users. + +Implementations that provide a means for defining custom functions +MUST provide a means for _function handlers_ +to return _resolved values_ that contain enough information +to be used as _operands_ or _option_ values in subsequent _expressions_. + +The _resolved value_ returned by a _function handler_ +MAY be different from the value of the _operand_ of the _function_. +It MAY be an implementation specified type. +It is not required to be the same type as the _operand_. + +A _function handler_ MAY include resolved options in its _resolved value_. +The resolved options MAY be different from the _options_ of the function. + +A _function handler_ SHOULD emit a +_Bad Operand_ error for _operands_ whose _resolved value_ +or type is not supported. + +_Function handler_ access to the _formatting context_ MUST be minimal and read-only, +and execution time SHOULD be limited. + +Implementation-defined _functions_ SHOULD use an implementation-defined _namespace_. #### Option Resolution @@ -313,7 +326,7 @@ For each _option_: - Resolve the _identifier_ of the _option_. - If the _option_'s right-hand side successfully resolves to a value, - bind the _identifier_ of the _option_ to the resolved value in the mapping. + bind the _identifier_ of the _option_ to the _resolved value_ in the mapping. - Otherwise, bind the _identifier_ of the _option_ to an unresolved value in the mapping. Implementations MAY later remove this value before calling the _function_. (Note that an _Unresolved Variable_ error will have been emitted.) @@ -326,7 +339,7 @@ This mapping can be empty. Unlike _functions_, the resolution of _markup_ is not customizable. -The resolved value of _markup_ includes the following fields: +The _resolved value_ of _markup_ includes the following fields: - The type of the markup: open, standalone, or close - The _identifier_ of the _markup_ @@ -336,7 +349,7 @@ The resolution of _markup_ MUST always succeed. ### Fallback Resolution -A **_fallback value_** is the resolved value for an _expression_ that fails to resolve. +A **_fallback value_** is the _resolved value_ for an _expression_ that fails to resolve. An _expression_ fails to resolve when: @@ -400,6 +413,23 @@ _Option_ _identifiers_ and values are not included in the _fallback value_. _Pattern selection_ is not supported for _fallback values_. +> For example, in a JavaScript formatter +> the _fallback value_ could have the following implementation, +> where `source` is one of the above-defined strings: +> +> ```ts +> class MessageFallback implements MessageValue { +> constructor(source: string) { +> this.formatToString = () => `{${source}}`; +> this.getValue = () => undefined; +> } +> resolvedOptions: () => ({}); +> selectKeys(_keys: string[]) { +> throw Error("Selection on fallback values is not supported"); +> } +> } +> ``` + ## Pattern Selection If the _message_ being formatted is not _well-formed_ and _valid_, @@ -478,17 +508,17 @@ as long as its observable behavior matches the results of the method defined her First, resolve the values of each _selector_: -1. Let `res` be a new empty list of resolved values that support selection. +1. Let `res` be a new empty list of _resolved values_ that support selection. 1. For each _selector_ `sel`, in source order, - 1. Let `rv` be the resolved value of `sel`. + 1. Let `rv` be the _resolved value_ of `sel`. 1. If selection is supported for `rv`: 1. Append `rv` as the last element of the list `res`. 1. Else: - 1. Let `nomatch` be a resolved value for which selection always fails. + 1. Let `nomatch` be a _resolved value_ for which selection always fails. 1. Append `nomatch` as the last element of the list `res`. 1. Emit a _Bad Selector_ error. -The form of the resolved values is determined by each implementation, +The form of the _resolved values_ is determined by each implementation, along with the manner of determining their support for selection. ### Resolve Preferences @@ -502,9 +532,9 @@ Next, using `res`, resolve the preferential order for all message keys: 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` in Unicode Normalization Form C. + 1. Let `ks` be the _resolved value_ of `key` in Unicode Normalization Form C. 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 `rv` be the _resolved value_ at index `i` of `res`. 1. Let `matches` be the result of calling the method MatchSelectorKeys(`rv`, `keys`) 1. Append `matches` as the last element of the list `pref`. @@ -535,7 +565,7 @@ filter the list of _variants_ to the ones that match with some preference: 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 `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`. @@ -561,7 +591,7 @@ Finally, sort the list of variants `vars` and select the _pattern_: 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 `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 the result of calling the method `SortVariants(sortable)`. @@ -711,7 +741,7 @@ one {{Category match for {$count}}} After _pattern selection_, each _text_ and _placeholder_ part of the selected _pattern_ is resolved and formatted. -Resolved values cannot always be formatted by a given implementation. +_Resolved values_ cannot always be formatted by a given implementation. When such an error occurs during _formatting_, an appropriate _Message Function Error_ is emitted and a _fallback value_ is used for the _placeholder_ with the error. @@ -721,8 +751,8 @@ appropriate data type or structure. Some examples of these include: - A single string concatenated from the parts of the resolved _pattern_. - A string with associated attributes for portions of its text. -- A flat sequence of objects corresponding to each resolved value. -- A hierarchical structure of objects that group spans of resolved values, +- A flat sequence of objects corresponding to each _resolved value_. +- A hierarchical structure of objects that group spans of _resolved values_, such as sequences delimited by _markup-open_ and _markup-close_ _placeholders_. Implementations SHOULD provide _formatting_ result types that match user needs, @@ -837,7 +867,7 @@ The _Default Bidi Strategy_ is defined as follows: These correspond to the message having left-to-right directionality, right-to-left directionality, and to the message's directionality not being known. 1. For each _expression_ `exp` in _pattern_: - 1. Let `fmt` be the formatted string representation of the resolved value of `exp`. + 1. Let `fmt` be the formatted string representation of the _resolved value_ of `exp`. 1. Let `dir` be the directionality of `fmt`, one of « `'LTR'`, `'RTL'`, `'unknown'` », with the same meanings as for `msgdir`. 1. If `dir` is `'LTR'`: diff --git a/spec/registry.md b/spec/registry.md index d89b957055..a962ed09b7 100644 --- a/spec/registry.md +++ b/spec/registry.md @@ -1,7 +1,7 @@ # MessageFormat 2.0 Default Function Registry -This section describes the functions which each implementation MUST provide -to be conformant with this specification. +This section describes the functions for which each implementation MUST provide +a _function handler_ to be conformant with this specification. Implementations MAY implement additional _functions_ or additional _options_. In particular, implementations are encouraged to provide feedback on proposed @@ -51,7 +51,7 @@ The function `:string` has no options. #### Selection When implementing [`MatchSelectorKeys(resolvedSelector, keys)`](/spec/formatting.md#resolve-preferences) -where `resolvedSelector` is the resolved value of a _selector_ +where `resolvedSelector` is the _resolved value_ of a _selector_ and `keys` is a list of strings, the `:string` selector function performs as described below. @@ -88,7 +88,7 @@ the `:string` selector function performs as described below. #### Formatting -The `:string` function returns the string value of the resolved value of the _operand_. +The `:string` function returns the string value of the _resolved value_ of the _operand_. ## Numeric Value Selection and Formatting @@ -374,12 +374,12 @@ All other values produce a _Bad Operand_ error. ### Digit Size Options Some _options_ of number _functions_ are defined to take a "digit size option". -Implementations of number _functions_ use these _options_ to control aspects of numeric display +The _function handlers_ for number _functions_ use these _options_ to control aspects of numeric display such as the number of fraction, integer, or significant digits. A "digit size option" is an _option_ value that the _function_ interprets as a small integer value greater than or equal to zero. -Implementations MAY define an upper limit on the resolved value +Implementations MAY define an upper limit on the _resolved value_ of a digit size option option consistent with that implementation's practical limits. In most cases, the value of a digit size option will be a string that @@ -404,7 +404,7 @@ Number selection has three modes: followed by an ordinal rule category if there is no explicit match When implementing [`MatchSelectorKeys(resolvedSelector, keys)`](/spec/formatting.md#resolve-preferences) -where `resolvedSelector` is the resolved value of a _selector_ +where `resolvedSelector` is the _resolved value_ of a _selector_ and `keys` is a list of strings, numeric selectors perform as described below. @@ -448,7 +448,7 @@ but a weaker match than any exact match _key_ value. The rules for a given locale might not produce all of the keywords. A given _operand_ value might produce different keywords depending on the locale. -Apply the rules to the resolved value of the _operand_ and the relevant function _options_, +Apply the rules to the _resolved value_ of the _operand_ and the relevant function _options_, and return the resulting keyword. If no rules match, return `other`. @@ -554,7 +554,7 @@ or can use a collection of _field options_ (but not both) to control the formatt output. If both are specified, a _Bad Option_ error MUST be emitted -and a _fallback value_ used as the resolved value of the _expression_. +and a _fallback value_ used as the _resolved value_ of the _expression_. > [!NOTE] > The names of _options_ and their _values_ were derived from the @@ -579,8 +579,6 @@ The function `:datetime` has these _style options_. _Field options_ describe which fields to include in the formatted output and what format to use for that field. -The implementation may use this _function_ to configure which fields -appear in the formatted output. > [!NOTE] > _Field options_ do not have default values because they are only to be used diff --git a/spec/syntax.md b/spec/syntax.md index 24ea52318f..a31c3f9215 100644 --- a/spec/syntax.md +++ b/spec/syntax.md @@ -97,7 +97,7 @@ Attempting to parse a _message_ that is not _valid_ will result in a _Data Model A **_message_** is the complete template for a specific message formatting request. -A **_variable_** is a _name_ associated to a resolved value. +A **_variable_** is a _name_ associated to a _resolved value_. An **_external variable_** is a _variable_ whose _name_ and initial value are supplied by the caller @@ -195,7 +195,7 @@ An **_input-declaration_** binds a _variable_ to an external input va The _variable-expression_ of an _input-declaration_ MAY include a _function_ that is applied to the external value. -A **_local-declaration_** binds a _variable_ to the resolved value of an _expression_. +A **_local-declaration_** binds a _variable_ to the _resolved value_ of an _expression_. ```abnf declaration = input-declaration / local-declaration @@ -379,7 +379,7 @@ match-statement = match 1*(s selector) ### Selector -A **_selector_** is a _variable_ whose resolved value ranks or excludes the +A **_selector_** is a _variable_ whose _resolved value_ ranks or excludes the _variants_ based on the value of the corresponding _key_ in each _variant_. The combination of _selectors_ in a _matcher_ thus determines which _pattern_ will be used during formatting. diff --git a/test/README.md b/test/README.md index dabde2aa20..6fa50dfc50 100644 --- a/test/README.md +++ b/test/README.md @@ -84,8 +84,8 @@ its `Input`, `DecimalPlaces`, `FailsFormat`, and `FailsSelect` values are determ 1. Let `DecimalPlaces` be 0. 1. Let `FailsFormat` be `false`. 1. Let `FailsSelect` be `false`. -1. Let `arg` be the resolved value of the _expression_ _operand_. -1. If `arg` is the resolved value of an _expression_ +1. Let `arg` be the _resolved value_ of the _expression_ _operand_. +1. If `arg` is the _resolved value_ of an _expression_ with a `:test:function`, `:test:select`, or `:test:format` _annotation_ for which resolution has succeeded, then 1. Let `Input` be the `Input` value of `arg`. @@ -97,7 +97,7 @@ its `Input`, `DecimalPlaces`, `FailsFormat`, and `FailsSelect` values are determ 1. Let `Input` be the numerical value of `arg`. 1. Else, 1. Emit "bad-input" _Resolution Error_. - 1. Use a _fallback value_ as the resolved value of the _expression_. + 1. Use a _fallback value_ as the _resolved value_ of the _expression_. Further steps of this algorithm are not followed. 1. If the `decimalPlaces` _option_ is set, then 1. If its value resolves to a numerical integer value 0 or 1 @@ -105,7 +105,7 @@ its `Input`, `DecimalPlaces`, `FailsFormat`, and `FailsSelect` values are determ 1. Set `DecimalPlaces` to be the numerical value of the _option_. 1. Else if its value is not an unresolved value set by _option resolution_, 1. Emit "bad-option" _Resolution Error_. - 1. Use a _fallback value_ as the resolved value of the _expression_. + 1. Use a _fallback value_ as the _resolved value_ of the _expression_. 1. If the `fails` _option_ is set, then 1. If its value resolves to the string `'always'`, then 1. Set `FailsFormat` to be `true`. @@ -133,7 +133,7 @@ depends on its `Input`, `DecimalPlaces` and `FailsSelect` values. When an _expression_ with a `:test:function` _annotation_ is assigned to a _variable_ by a _declaration_ and that _variable_ is used as an _option_ value, -its resolved value is the `Input` value. +its _resolved value_ is the `Input` value. When `:test:function` is used as a _formatter_, a _placeholder_ resolving to a value with a `:test:function` _expression_