Skip to content

Commit 6414b6c

Browse files
eemeliaphillips
andauthored
Add :test:function, :test:select, and :test:format function definitions (#769)
* Add test:number and test:plural function definitions * Rename as test:func & test:select, add test:format * Apply suggestions from code review * Add "Operands" and "Options" sections to look like registry.md function definitions * Apply suggestions from code review Co-authored-by: Addison Phillips <[email protected]> * Linkify all the things * Drop note about not rounding * Rename FD as DecimalPlaces --------- Co-authored-by: Addison Phillips <[email protected]>
1 parent f111102 commit 6414b6c

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

test/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,103 @@ Some examples of test harnesses using these tests, from the source repository:
2323
A [JSON schema](./schemas/) is included for the test files in this repository.
2424

2525
For users of Visual Studio Code, a [settings file](./.vscode/settings.json) is included that enables schema validation while editing the test files.
26+
27+
## Test Functions
28+
29+
As the behaviour of some of the default registry _functions_
30+
such as `:number` and `:datetime`
31+
is dependent on locale-specific data and may vary between implementations,
32+
the following _functions_ are defined for **test use only**:
33+
34+
### `:test:function`
35+
36+
This function is valid both as a _selector_ and as a _formatter_.
37+
38+
#### Operands
39+
40+
The function `:test:function` requires a [Number Operand](/spec/registry.md#number-operands) as its _operand_.
41+
42+
#### Options
43+
44+
The only _option_ `:test:function` recognizes is `decimalPlaces`,
45+
a _digit size option_ for which only `0` and `1` are valid values.
46+
47+
All other _options_ and their values are ignored.
48+
49+
#### Behavior
50+
51+
When resolving a `:test:function` expression,
52+
its `Input` and `DecimalPlaces` values are determined as follows:
53+
54+
1. Let `DecimalPlaces` be 0.
55+
1. Let `arg` be the resolved value of the _expression_ _operand_.
56+
1. If `arg` is the resolved value of an _expression_
57+
with a `:test:function`, `:test:select`, or `:test:format` _annotation_
58+
for which resolution has succeeded, then
59+
1. Let `Input` be the `Input` value of `arg`.
60+
1. Set `DecimalPlaces` to be `DecimalPlaces` value of `arg`.
61+
1. Else if `arg` is a numerical value
62+
or a string matching the `number-literal` production, then
63+
1. Let `Input` be the numerical value of `arg`.
64+
1. Else,
65+
1. Emit "bad-input" _Resolution Error_.
66+
1. Use a _fallback value_ as the resolved value of the _expression_.
67+
Further steps of this algorithm are not followed.
68+
1. If the `decimalPlaces` _option_ is set, then
69+
1. If its value resolves to a numerical integer value 0 or 1
70+
or their corresponding string representations `'0'` or `'1'`, then
71+
1. Set `DecimalPlaces` to be the numerical value of the _option_.
72+
1. Else if its value is not an unresolved value set by _option resolution_,
73+
1. Emit "bad-option" _Resolution Error_.
74+
1. Use a _fallback value_ as the resolved value of the _expression_.
75+
76+
When `:test:function` is used as a _selector_,
77+
the behaviour of calling it as the `rv` value of MatchSelectorKeys(`rv`, `keys`)
78+
(see [Resolve Preferences](/spec/formatting.md#resolve-preferences) for more information)
79+
depends on its `Input` and `DecimalPlaces` values.
80+
81+
- If the `Input` is 1 and `DecimalPlaces` is 1,
82+
the method will return some slice of the list « `'1.0'`, `'1'` »,
83+
depending on whether those values are included in `keys`.
84+
- If the `Input` is 1 and `DecimalPlaces` is 0,
85+
the method will return the list « `'1'` » if `keys` includes `'1'`, or an empty list otherwise.
86+
- If the `Input` is any other value, the method will return an empty list.
87+
88+
When an _expression_ with a `:test:function` _annotation_ is assigned to a _variable_ by a _declaration_
89+
and that _variable_ is used as an _option_ value,
90+
its resolved value is the `Input` value.
91+
92+
When `:test:function` is used as a _formatter_,
93+
a _placeholder_ resolving to a value with a `:test:function` _expression_
94+
is formatted as a concatenation of the following parts:
95+
96+
1. If `Input` is less than 0, the character `-` U+002D Hyphen-Minus.
97+
1. The truncated absolute integer value of `Input`, i.e. floor(abs(`Input`)),
98+
formatted as a sequence of decimal digit characters (U+0030...U+0039).
99+
1. If `DecimalPlaces` is 1, then
100+
1. The character `.` U+002E Full Stop.
101+
1. The single decimal digit character representing the value floor((abs(`Input`) - floor(abs(`Input`))) \* 10)
102+
103+
If the formatting target is a sequence of parts,
104+
each of the above parts will be emitted separately
105+
rather than being concatenated into a single string.
106+
107+
108+
### `:test:select`
109+
110+
This _function_ accepts the same _operands_ and _options_,
111+
and behaves exactly the same as `:test:function`,
112+
except that it cannot be used for formatting.
113+
114+
When `:test:select` is used as a _formatter_,
115+
a "not-formattable" error is emitted and the _placeholder_ is formatted with
116+
a _fallback value_.
117+
118+
### `:test:format`
119+
120+
This _function_ accepts the same _operands_ and _options_,
121+
and behaves exactly the same as `:test:function`,
122+
except that it cannot be used for selection.
123+
124+
When `:test:format` is used as a _selector_,
125+
the steps under 2.iii. of [Resolve Selectors](/spec/formatting.md#resolve-selectors) are followed.

0 commit comments

Comments
 (0)