Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f3344b5

Browse files
eemeliaphillipscatamorphismgibson042
authored
Fix fallback value definition and use (#903)
* Fix references to fallback values * Apply suggestions from code review Co-authored-by: Addison Phillips <[email protected]> * Apply suggestions from code review Co-authored-by: Tim Chevalier <[email protected]> * Apply suggestions from code review Co-authored-by: Richard Gibson <[email protected]> * Typo fix * Note that operand options are not handled by Option Resolution * Apply suggestions from code review * Fix typo Co-authored-by: Tim Chevalier <[email protected]> * Use last rather than earliest operand for fallback value * Use last name also during fallback in variable resolution * Add tests for fallback formatting * Tighten up language about fallback values, their string representations, and options * Add "if supported" qualifier to emitting Bad Option error during option resolution Co-authored-by: Addison Phillips <[email protected]> --------- Co-authored-by: Addison Phillips <[email protected]> Co-authored-by: Tim Chevalier <[email protected]> Co-authored-by: Richard Gibson <[email protected]>
1 parent 852c5e2 commit f3344b5

File tree

3 files changed

+131
-75
lines changed

3 files changed

+131
-75
lines changed

spec/formatting.md

Lines changed: 73 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,7 @@ whether its value was originally a _quoted literal_ or an _unquoted literal_.
231231
> For example,
232232
> the _option_ `foo=42` and the _option_ `foo=|42|` are treated as identical.
233233
234-
235-
> For example, in a JavaScript formatter
234+
> For example, in a JavaScript formatter,
236235
> the _resolved value_ of a _text_ or a _literal_ could have the following implementation:
237236
>
238237
> ```ts
@@ -257,23 +256,30 @@ Otherwise, the _variable_ is an implicit reference to an input value,
257256
and its value is looked up from the _formatting context_ _input mapping_.
258257
259258
The resolution of a _variable_ fails if no value is identified for its _name_.
260-
If this happens, an _Unresolved Variable_ error is emitted.
261-
If a _variable_ would resolve to a _fallback value_,
262-
this MUST also be considered a failure.
259+
If this happens, an _Unresolved Variable_ error is emitted
260+
and a _fallback value_ is used as the _resolved value_ of the _variable_.
261+
262+
If the _resolved value_ identified for the _variable_ _name_ is a _fallback value_,
263+
a _fallback value_ is used as the _resolved value_ of the _variable_.
264+
265+
The _fallback value_ representation of a _variable_ has a string representation
266+
consisting of the U+0024 DOLLAR SIGN `$` followed by the _name_ of the _variable_.
263267
264268
### Function Resolution
265269
266270
To resolve an _expression_ with a _function_,
267271
the following steps are taken:
268272
269273
1. If the _expression_ includes an _operand_, resolve its value.
270-
If this fails, use a _fallback value_ for the _expression_.
271-
2. Resolve the _identifier_ of the _function_ and, based on the starting sigil,
274+
If this is a _fallback value_,
275+
return a _fallback value_ as the _resolved value_ of the _expression_.
276+
277+
2. Resolve the _identifier_ of the _function_ and
272278
find the appropriate _function handler_ to call.
273279
If the implementation cannot find the _function handler_,
274280
or if the _identifier_ includes a _namespace_ that the implementation does not support,
275281
emit an _Unknown Function_ error
276-
and use a _fallback value_ for the _expression_.
282+
and return a _fallback value_ as the _resolved value_ of the _expression_.
277283
278284
Implementations are not required to implement _namespaces_ or installable
279285
_function registries_.
@@ -294,7 +300,7 @@ the following steps are taken:
294300
supported by the implementation, process them as specified.
295301
Such `u:` options MAY be removed from the resolved mapping of _options_.
296302
297-
5. Call the function implementation with the following arguments:
303+
5. Call the _function handler_ with the following arguments:
298304
299305
- The _function context_.
300306
- The resolved mapping of _options_.
@@ -318,7 +324,7 @@ the following steps are taken:
318324
_operand_ did not match that expected by the _function_,
319325
the _function_ SHOULD cause a _Bad Operand_ error to be emitted.
320326
321-
In all failure cases, use the _fallback value_ for the _expression_ as its _resolved value_.
327+
In all failure cases, return a _fallback value_ as the _resolved value_ of the _expression_.
322328
323329
#### Function Handler
324330
@@ -366,17 +372,27 @@ The order of _options_ MUST NOT be significant.
366372
367373
For each _option_:
368374
369-
- Resolve the _identifier_ of the _option_.
370-
- If the _option_'s right-hand side successfully resolves to a value,
371-
bind the _identifier_ of the _option_ to the _resolved value_ in the mapping.
372-
- Otherwise, bind the _identifier_ of the _option_ to an unresolved value in the mapping.
373-
Implementations MAY later remove this value before calling the _function_.
374-
(Note that an _Unresolved Variable_ error will have been emitted.)
375+
1. Let `res` be a new empty mapping.
376+
1. For each _option_:
377+
1. Let `id` be the string value of the _identifier_ of the _option_.
378+
1. Let `rv` be the _resolved value_ of the _option_ value.
379+
1. If `rv` is a _fallback value_:
380+
1. If supported, emit a _Bad Option_ error.
381+
1. Else:
382+
1. Set `res[id]` to be `rv`.
383+
1. Return `res`.
375384
376-
Errors MAY be emitted during _option resolution_,
377-
but it always resolves to some mapping of string identifiers to values.
385+
The result of _option resolution_ MUST be a (possibly empty) mapping
386+
of string identifiers to values;
387+
that is, errors MAY be emitted, but such errors MUST NOT be fatal.
378388
This mapping can be empty.
379389
390+
> [!NOTE]
391+
> The _resolved value_ of a _function_ _operand_
392+
> can also include resolved option values.
393+
> These are not included in the _option resolution_ result,
394+
> and need to be processed separately by a _function handler_.
395+
380396
### Markup Resolution
381397
382398
Unlike _functions_, the resolution of _markup_ is not customizable.
@@ -395,67 +411,73 @@ The resolution of _markup_ MUST always succeed.
395411
396412
### Fallback Resolution
397413
398-
A **_<dfn>fallback value</dfn>_** is the _resolved value_ for an _expression_ that fails to resolve.
414+
A **_<dfn>fallback value</dfn>_** is the _resolved value_ for
415+
an _expression_ or _variable_ when that _expression_ or _variable_ fails to resolve.
416+
It contains a string representation that is used for its formatting,
417+
and no option values.
418+
419+
The _resolved value_ of _text_, _literal_, and _markup_ MUST NOT be a _fallback value_.
420+
421+
A _variable_ fails to resolve when no value is identified for its _name_.
422+
The string representation of its _fallback value_ is
423+
U+0024 DOLLAR SIGN `$` followed by the _name_ of the _variable_.
399424
400425
An _expression_ fails to resolve when:
401426
402-
- A _variable_ used as an _operand_ (with or without a _function_) fails to resolve.
403-
* Note that this does not include a _variable_ used as an _option_ value.
404-
- A _function_ fails to resolve.
427+
- A _variable_ used as its _operand_ resolves to a _fallback value_.
428+
Note that an _expression_ does not necessarily fail to resolve
429+
if an _option_ resolves with a _fallback value_.
430+
- No _function handler_ is found for a _function_ _identifier_.
431+
- Calling a _function handler_ fails or does not return a valid value.
405432
406-
The _fallback value_ depends on the contents of the _expression_:
433+
The string representation of the _fallback value_ of an _expression_ depends on its contents:
407434
408-
- _expression_ with a _literal_ _operand_ (either quoted or unquoted)
435+
- _expression_ with a _literal_ _operand_ (either quoted or unquoted):
409436
U+007C VERTICAL LINE `|`
410437
followed by the value of the _literal_
411438
with escaping applied to U+005C REVERSE SOLIDUS `\` and U+007C VERTICAL LINE `|`,
412439
and then by U+007C VERTICAL LINE `|`.
413440
414441
> Examples:
415442
> In a context where `:func` fails to resolve,
416-
> `{42 :func}` resolves to the _fallback value_ `|42|` and
417-
> `{|C:\\| :func}` resolves to the _fallback value_ `|C:\\|`.
443+
> `{42 :func}` resolves to a _fallback value_ with a string representation `|42|` and
444+
> `{|C:\\| :func}` resolves to a _fallback value_ with a string representation `|C:\\|`.
418445
419-
- _expression_ with _variable_ _operand_ referring to a local _declaration_ (with or without a _function_):
420-
the _value_ to which it resolves (which may already be a _fallback value_)
421-
422-
> Examples:
423-
> In a context where `:func` fails to resolve,
424-
> the _pattern_'s _expression_ in `.local $var={|val|} {{{$var :func}}}`
425-
> resolves to the _fallback value_ `|val|` and the message formats to `{|val|}`.
426-
> In a context where `:now` fails to resolve but `:datetime` does not,
427-
> the _pattern_'s _expression_ in
428-
> ```
429-
> .local $t = {:now format=iso8601}
430-
> .local $pretty_t = {$t :datetime}
431-
> {{{$pretty_t}}}
432-
> ```
433-
> (transitively) resolves to the _fallback value_ `:now` and
434-
> the message formats to `{:now}`.
435-
436-
- _expression_ with _variable_ _operand_ not referring to a local _declaration_ (with or without a _function_):
446+
- _expression_ with _variable_ _operand_:
447+
the _fallback value_ representation of that _variable_,
437448
U+0024 DOLLAR SIGN `$` followed by the _name_ of the _variable_
438449
439450
> Examples:
440451
> In a context where `$var` fails to resolve, `{$var}` and `{$var :number}`
441-
> both resolve to the _fallback value_ `$var`.
452+
> both resolve to a _fallback value_ with a string representation `$var`
453+
> (even if `:number` fails to resolve).
454+
>
442455
> In a context where `:func` fails to resolve,
443-
> the _pattern_'s _expression_ in `.input $arg {{{$arg :func}}}`
444-
> resolves to the _fallback value_ `$arg` and
445-
> the message formats to `{$arg}`.
456+
> the _placeholder_ in `.local $var = {|val| :func} {{{$var}}}`
457+
> resolves to a _fallback value_ with a string representation `$var`.
458+
>
459+
> In a context where either `:now` or `:pretty` fails to resolve,
460+
> the _placeholder_ in
461+
> ```
462+
> .local $time = {:now format=iso8601}
463+
> {{{$time :pretty}}}
464+
> ```
465+
> resolves to a _fallback value_ with a string representation `$time`.
446466
447467
- _function_ _expression_ with no _operand_:
448468
U+003A COLON `:` followed by the _function_ _identifier_
449469
450470
> Examples:
451-
> In a context where `:func` fails to resolve, `{:func}` resolves to the _fallback value_ `:func`.
452-
> In a context where `:ns:func` fails to resolve, `{:ns:func}` resolves to the _fallback value_ `:ns:func`.
471+
> In a context where `:func` fails to resolve,
472+
> `{:func}` resolves to a _fallback value_ with a string representation `:func`.
473+
> In a context where `:ns:func` fails to resolve,
474+
> `{:ns:func}` resolves to a _fallback value_ with a string representation `:ns:func`.
453475
454476
- Otherwise: the U+FFFD REPLACEMENT CHARACTER `�`
455477
456478
This is not currently used by any expression, but may apply in future revisions.
457479
458-
_Option_ _identifiers_ and values are not included in the _fallback value_.
480+
_Options_ and _attributes_ are not included in the _fallback value_.
459481
460482
_Pattern selection_ is not supported for _fallback values_.
461483

test/tests/fallback.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/unicode-org/message-format-wg/main/test/schemas/v0/tests.schema.json",
3+
"scenario": "Fallback",
4+
"description": "Test cases for fallback behaviour.",
5+
"defaultTestProperties": {
6+
"bidiIsolation": "none",
7+
"locale": "en-US",
8+
"expErrors": true
9+
},
10+
"tests": [
11+
{
12+
"description": "function with unquoted literal operand",
13+
"src": "{42 :test:function fails=format}",
14+
"exp": "{|42|}"
15+
},
16+
{
17+
"description": "function with quoted literal operand",
18+
"src": "{|C:\\\\| :test:function fails=format}",
19+
"exp": "{|C:\\\\|}"
20+
},
21+
{
22+
"description": "unannotated implicit input variable",
23+
"src": "{$var}",
24+
"exp": "{$var}"
25+
},
26+
{
27+
"description": "annotated implicit input variable",
28+
"src": "{$var :number}",
29+
"exp": "{$var}"
30+
},
31+
{
32+
"description": "local variable with unknown function in declaration",
33+
"src": ".local $var = {|val| :test:undefined} {{{$var}}}",
34+
"exp": "{$var}"
35+
},
36+
{
37+
"description": "function with local variable operand with unknown function in declaration",
38+
"src": ".local $var = {|val| :test:undefined} {{{$var :test:function}}}",
39+
"exp": "{$var}"
40+
},
41+
{
42+
"description": "local variable with unknown function in placeholder",
43+
"src": ".local $var = {|val|} {{{$var :test:undefined}}}",
44+
"exp": "{$var}"
45+
},
46+
{
47+
"description": "function with no operand",
48+
"src": "{:test:undefined}",
49+
"exp": "{:test:undefined}"
50+
}
51+
]
52+
}

test/tests/functions/number.json

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -132,33 +132,15 @@
132132
},
133133
{
134134
"src": ".local $foo = {$bar :number minimumFractionDigits=foo} {{bar {$foo}}}",
135-
"params": [
136-
{
137-
"name": "bar",
138-
"value": 4.2
139-
}
140-
],
141-
"exp": "bar {$bar}",
142-
"expErrors": [
143-
{
144-
"type": "bad-option"
145-
}
146-
]
135+
"params": [{ "name": "bar", "value": 4.2 }],
136+
"exp": "bar {$foo}",
137+
"expErrors": [{ "type": "bad-option" }]
147138
},
148139
{
149140
"src": ".local $foo = {$bar :number} {{bar {$foo}}}",
150-
"params": [
151-
{
152-
"name": "bar",
153-
"value": "foo"
154-
}
155-
],
156-
"exp": "bar {$bar}",
157-
"expErrors": [
158-
{
159-
"type": "bad-operand"
160-
}
161-
]
141+
"params": [{ "name": "bar", "value": "foo" }],
142+
"exp": "bar {$foo}",
143+
"expErrors": [{ "type": "bad-operand" }]
162144
},
163145
{
164146
"src": ".input {$foo :number} {{bar {$foo}}}",

0 commit comments

Comments
 (0)