Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :test:function, :test:select, and :test:format function definitions #769

Merged
merged 9 commits into from
May 13, 2024
100 changes: 100 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,103 @@ Some examples of test harnesses using these tests, from the source repository:
A [JSON schema](./schemas/) is included for the test files in this repository.

For users of Visual Studio Code, a [settings file](./.vscode/settings.json) is included that enables schema validation while editing the test files.
eemeli marked this conversation as resolved.
Show resolved Hide resolved

## Test Functions

As the behaviour of some of the default registry _functions_
such as `:number` and `:datetime`
is dependent on locale-specific data and may vary between implementations,
the following _functions_ are defined for **test use only**:

### `:test:function`

This function is valid both as a _selector_ and as a _formatter_.

#### Operands

The function `:test:function` requires a [Number Operand](/spec/registry.md#number-operands) as its _operand_.

#### Options

The only _option_ `:test:function` recognizes is `decimalPlaces`,
a _digit size option_ for which only `0` and `1` are valid values.
echeran marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linkifying digit size just as "Number Operand" is being linkified 5 lines above. Helps short circuit questions like mine for the reader.

Suggested change
a _digit size option_ for which only `0` and `1` are valid values.
a [_digit size option_](/spec/registry.md#digit-size-options) for which only `0` and `1` are valid values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Underscore italics are linkified when the spec is turned into HTML. That's what this is for.


All other _options_ and their values are ignored.

#### Behavior

When resolving a `:test:function` expression,
its `Input` and `DecimalPlaces` values are determined as follows:

1. Let `DecimalPlaces` be 0.
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`.
1. Set `DecimalPlaces` to be `DecimalPlaces` value of `arg`.
1. Else if `arg` is a numerical value
or a string matching the `number-literal` production, then
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_.
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
or their corresponding string representations `'0'` or `'1'`, then
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_.

When `:test:function` is used as a _selector_,
the behaviour of calling it as the `rv` value of MatchSelectorKeys(`rv`, `keys`)
(see [Resolve Preferences](/spec/formatting.md#resolve-preferences) for more information)
depends on its `Input` and `DecimalPlaces` values.

- If the `Input` is 1 and `DecimalPlaces` is 1,
the method will return some slice of the list « `'1.0'`, `'1'` »,
depending on whether those values are included in `keys`.
- If the `Input` is 1 and `DecimalPlaces` is 0,
the method will return the list « `'1'` » if `keys` includes `'1'`, or an empty list otherwise.
- If the `Input` is any other value, the method will return an empty list.

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.

When `:test:function` is used as a _formatter_,
a _placeholder_ resolving to a value with a `:test:function` _expression_
is formatted as a concatenation of the following parts:

1. If `Input` is less than 0, the character `-` U+002D Hyphen-Minus.
1. The truncated absolute integer value of `Input`, i.e. floor(abs(`Input`)),
formatted as a sequence of decimal digit characters (U+0030...U+0039).
1. If `DecimalPlaces` is 1, then
1. The character `.` U+002E Full Stop.
1. The single decimal digit character representing the value floor((abs(`Input`) - floor(abs(`Input`))) \* 10)

If the formatting target is a sequence of parts,
each of the above parts will be emitted separately
rather than being concatenated into a single string.


### `:test:select`

This _function_ accepts the same _operands_ and _options_,
and behaves exactly the same as `:test:function`,
except that it cannot be used for formatting.
echeran marked this conversation as resolved.
Show resolved Hide resolved

When `:test:select` is used as a _formatter_,
a "not-formattable" error is emitted and the _placeholder_ is formatted with
a _fallback value_.

### `:test:format`
echeran marked this conversation as resolved.
Show resolved Hide resolved

This _function_ accepts the same _operands_ and _options_,
and behaves exactly the same as `:test:function`,
except that it cannot be used for selection.

When `:test:format` is used as a _selector_,
the steps under 2.iii. of [Resolve Selectors](/spec/formatting.md#resolve-selectors) are followed.