Skip to content

Commit 3c21782

Browse files
committed
Add a :math function, for addition and subtraction
1 parent 51b0d5d commit 3c21782

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

spec/registry.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,69 @@ together with the resolved options' values.
381381
382382
The _function_ `:integer` performs selection as described in [Number Selection](#number-selection) below.
383383
384+
### The `:math` function
385+
386+
The function `:math` is a selector and formatter for matching or formatting
387+
numeric values to which a mathematical operation has been applied.
388+
389+
> This function is useful for plural selection and formatting of an offset of an input value.
390+
> For example, it can be used in a message such as this:
391+
> ```
392+
> .input {$like_count :integer}
393+
> .local $others_count = {$like_count :math subtract=1}
394+
> .match $like_count $others_count
395+
> 0 * {{Your post has no likes.}}
396+
> 1 * {{{$name} liked your post.}}
397+
> * 1 {{{$name} and one other person liked your post.}}
398+
> * * {{{$name} and {$others_count} other people liked your post.}}
399+
> ```
400+
401+
#### Operands
402+
403+
The function `:math` requires a [Number Operand](#number-operands) as its _operand_.
404+
405+
#### Options
406+
407+
The options on `:math` are exclusive with each other,
408+
and exactly one option is always required.
409+
The options do not have default values.
410+
411+
The following options and their values are
412+
required in the default registry to be available on the function `:math`:
413+
- `add`
414+
- ([digit size option](#digit-size-options))
415+
- `subtract`
416+
- ([digit size option](#digit-size-options))
417+
418+
If no options or more than one option is set,
419+
or if an _option_ value is not a [digit size option](#digit-size-options),
420+
a _Bad Option_ error is emitted
421+
and a _fallback value_ used as the _resolved value_ of the _expression_.
422+
423+
#### Resolved Value
424+
425+
The _resolved value_ of an _expression_ with a `:math` _function_
426+
contains the implementation-defined numeric value
427+
of the _operand_ of the annotated _expression_.
428+
429+
If the `add` option is set,
430+
the numeric value of the _resolved value_ is formed by incrementing
431+
the numeric value of the _operand_ by the integer value of the digit size option value.
432+
433+
If the `subtract` option is set,
434+
the numeric value of the _resolved value_ is formed by decrementing
435+
the numeric value of the _operand_ by the integer value of the digit size option value.
436+
437+
If the _operand_ of the _expression_ is an implementation-defined numeric type,
438+
such as the _resolved value_ of an _expression_ with a `:number` or `:integer` _annotation_,
439+
it can include option values.
440+
These are included in the resolved option values of the _expression_.
441+
The `:math` _options_ are not included in the resolved option values.
442+
443+
#### Selection
444+
445+
The _function_ `:math` performs selection as described in [Number Selection](#number-selection) below.
446+
384447
### Number Operands
385448
386449
The _operand_ of a number function is either an implementation-defined type or

test/tests/functions/math.json

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/unicode-org/message-format-wg/main/test/schemas/v0/tests.schema.json",
3+
"scenario": "Math function",
4+
"description": "The built-in formatter and selector for addition and subtraction.",
5+
"defaultTestProperties": {
6+
"bidiIsolation": "none",
7+
"locale": "en-US"
8+
},
9+
"tests": [
10+
{
11+
"src": "{:math add=13}",
12+
"expErrors": [{ "type": "bad-operand" }]
13+
},
14+
{
15+
"src": "{foo :math add=13}",
16+
"expErrors": [{ "type": "bad-operand" }]
17+
},
18+
{
19+
"src": "{42 :math}",
20+
"expErrors": [{ "type": "bad-option" }]
21+
},
22+
{
23+
"src": "{42 :math add=foo}",
24+
"expErrors": [{ "type": "bad-option" }]
25+
},
26+
{
27+
"src": "{42 :math subtract=foo}",
28+
"expErrors": [{ "type": "bad-option" }]
29+
},
30+
{
31+
"src": "{42 :math foo=13}",
32+
"expErrors": [{ "type": "bad-option" }]
33+
},
34+
{
35+
"src": "{42 :math add=13 subtract=13}",
36+
"expErrors": [{ "type": "bad-option" }]
37+
},
38+
{
39+
"src": "{41 :math add=1}",
40+
"exp": "42"
41+
},
42+
{
43+
"src": "{52 :math subtract=10}",
44+
"exp": "42"
45+
},
46+
{
47+
"src": "{41 :math add=1 foo=13}",
48+
"exp": "42"
49+
},
50+
{
51+
"src": ".local $x = {41 :integer signDisplay=always} {{{$x :math add=1}}}",
52+
"exp": "+42"
53+
},
54+
{
55+
"src": ".local $x = {52 :number signDisplay=always} {{{$x :math subtract=10}}}",
56+
"exp": "+42"
57+
},
58+
{
59+
"src": "{$x :math add=1}",
60+
"params": [{ "name": "x", "value": 41 }],
61+
"exp": "42"
62+
},
63+
{
64+
"src": "{$x :math subtract=10}",
65+
"params": [{ "name": "x", "value": 52 }],
66+
"exp": "42"
67+
},
68+
{
69+
"src": ".local $x = {1 :math add=1} .match $x 1 {{=1}} 2 {{=2}} * {{other}}",
70+
"exp": "=2"
71+
},
72+
{
73+
"src": ".local $x = {10 :integer} .local $y = {$x :math subtract=6} .match $y 10 {{=10}} 4 {{=4}} * {{other}}",
74+
"exp": "=4"
75+
}
76+
]
77+
}

0 commit comments

Comments
 (0)