Skip to content

Commit b6ba4bf

Browse files
eemeliaphillips
andauthored
Add a :math function, for addition and subtraction (#932)
* Add a :math function, for addition and subtraction * Clarify utility note Co-authored-by: Addison Phillips <[email protected]> * Add note on integer overflow Co-authored-by: Addison Phillips <[email protected]> --------- Co-authored-by: Addison Phillips <[email protected]>
1 parent 778d784 commit b6ba4bf

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

spec/registry.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,77 @@ together with the resolved options' values.
378378
379379
The _function_ `:integer` performs selection as described in [Number Selection](#number-selection) below.
380380
381+
### The `:math` function
382+
383+
The function `:math` is a selector and formatter for matching or formatting
384+
numeric values to which a mathematical operation has been applied.
385+
386+
> This function is useful for selection and formatting of values that
387+
> differ from the input value by a specified amount.
388+
> For example, it can be used in a message such as this:
389+
> ```
390+
> .input {$like_count :integer}
391+
> .local $others_count = {$like_count :math subtract=1}
392+
> .match $like_count $others_count
393+
> 0 * {{Your post has no likes.}}
394+
> 1 * {{{$name} liked your post.}}
395+
> * 1 {{{$name} and one other person liked your post.}}
396+
> * * {{{$name} and {$others_count} other people liked your post.}}
397+
> ```
398+
399+
#### Operands
400+
401+
The function `:math` requires a [Number Operand](#number-operands) as its _operand_.
402+
403+
#### Options
404+
405+
The options on `:math` are exclusive with each other,
406+
and exactly one option is always required.
407+
The options do not have default values.
408+
409+
The following options and their values are
410+
required in the default registry to be available on the function `:math`:
411+
- `add`
412+
- ([digit size option](#digit-size-options))
413+
- `subtract`
414+
- ([digit size option](#digit-size-options))
415+
416+
If no options or more than one option is set,
417+
or if an _option_ value is not a [digit size option](#digit-size-options),
418+
a _Bad Option_ error is emitted
419+
and a _fallback value_ used as the _resolved value_ of the _expression_.
420+
421+
#### Resolved Value
422+
423+
The _resolved value_ of an _expression_ with a `:math` _function_
424+
contains the implementation-defined numeric value
425+
of the _operand_ of the annotated _expression_.
426+
427+
If the `add` option is set,
428+
the numeric value of the _resolved value_ is formed by incrementing
429+
the numeric value of the _operand_ by the integer value of the digit size option value.
430+
431+
If the `subtract` option is set,
432+
the numeric value of the _resolved value_ is formed by decrementing
433+
the numeric value of the _operand_ by the integer value of the digit size option value.
434+
435+
If the _operand_ of the _expression_ is an implementation-defined numeric type,
436+
such as the _resolved value_ of an _expression_ with a `:number` or `:integer` _annotation_,
437+
it can include option values.
438+
These are included in the resolved option values of the _expression_.
439+
The `:math` _options_ are not included in the resolved option values.
440+
441+
> [!NOTE]
442+
> Implementations can encounter practical limits with `:math` _expressions_,
443+
> such as the result of adding two integers exceeding
444+
> the storage or precision of some implementation-defined number type.
445+
> In such cases, implementations can emit an _Unsupported Operation_ error
446+
> or they might just silently overflow the underlying data value.
447+
448+
#### Selection
449+
450+
The _function_ `:math` performs selection as described in [Number Selection](#number-selection) below.
451+
381452
### The `:currency` function
382453
383454
The function `:currency` is a selector and formatter for currency values,

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://github.com/raw/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)