Skip to content

Commit 0499c47

Browse files
committed
(third) Pass options to RuntimeValues, add NUMBER
1 parent 9c1b62b commit 0499c47

File tree

5 files changed

+130
-7
lines changed

5 files changed

+130
-7
lines changed

experiments/stasm/third/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Run each example individually:
7272
npm run example glossary
7373
npm run example phrases
7474
npm run example list
75+
npm run example number
7576

7677
## References
7778

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {Message} from "../impl/model.js";
2+
import {formatMessage, NumberValue} from "../impl/runtime.js";
3+
4+
console.log("==== English ====");
5+
6+
{
7+
// "Transferred {NUMBER $payloadSize STYLE unit UNIT megabyte}."
8+
let message: Message = {
9+
lang: "en",
10+
id: "transferred",
11+
phrases: {},
12+
selectors: [
13+
{
14+
expr: null,
15+
default: {type: "StringLiteral", value: "default"},
16+
},
17+
],
18+
variants: [
19+
{
20+
keys: [{type: "StringLiteral", value: "default"}],
21+
value: [
22+
{type: "StringLiteral", value: "Transferred "},
23+
{
24+
type: "FunctionCall",
25+
name: "NUMBER",
26+
args: [{type: "VariableReference", name: "payloadSize"}],
27+
opts: {
28+
STYLE: {type: "StringLiteral", value: "unit"},
29+
UNIT: {type: "StringLiteral", value: "megabyte"},
30+
},
31+
},
32+
{type: "StringLiteral", value: "."},
33+
],
34+
},
35+
],
36+
};
37+
console.log(
38+
formatMessage(message, {
39+
payloadSize: new NumberValue(1.23),
40+
})
41+
);
42+
}
43+
44+
console.log("==== French ====");
45+
46+
{
47+
// "{NUMBER $payloadSize STYLE unit UNIT megabyte} transféré."
48+
let message: Message = {
49+
lang: "fr",
50+
id: "transferred",
51+
phrases: {},
52+
selectors: [
53+
{
54+
expr: null,
55+
default: {type: "StringLiteral", value: "default"},
56+
},
57+
],
58+
variants: [
59+
{
60+
keys: [{type: "StringLiteral", value: "default"}],
61+
value: [
62+
{
63+
type: "FunctionCall",
64+
name: "NUMBER",
65+
args: [{type: "VariableReference", name: "payloadSize"}],
66+
opts: {
67+
STYLE: {type: "StringLiteral", value: "unit"},
68+
UNIT: {type: "StringLiteral", value: "megabyte"},
69+
},
70+
},
71+
{type: "StringLiteral", value: " transféré."},
72+
],
73+
},
74+
],
75+
};
76+
console.log(
77+
formatMessage(message, {
78+
payloadSize: new NumberValue(1.23),
79+
})
80+
);
81+
}

experiments/stasm/third/impl/registry.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ export type RegistryFunc<T> = (
99

1010
// The built-in functions.
1111
export const REGISTRY: Record<string, RegistryFunc<unknown>> = {
12-
PLURAL: get_plural,
12+
PLURAL: select_plural,
1313
PHRASE: get_phrase,
14+
NUMBER: format_number,
1415
};
1516

16-
function get_plural(
17+
function select_plural(
1718
ctx: FormattingContext,
1819
args: Array<Argument>,
1920
opts: Record<string, Parameter>
@@ -40,3 +41,31 @@ function get_phrase(
4041
let variant = ctx.selectVariant(phrase.variants, phrase.selectors);
4142
return new StringValue(ctx.formatPattern(variant.value));
4243
}
44+
45+
function format_number(
46+
ctx: FormattingContext,
47+
args: Array<Argument>,
48+
opts: Record<string, Parameter>
49+
): NumberValue {
50+
let number = ctx.toRuntimeValue(args[0]);
51+
if (!(number instanceof NumberValue)) {
52+
throw new TypeError();
53+
}
54+
55+
// TODO(stasm): Add more options.
56+
let opt_values: Record<string, boolean | number | string> = {};
57+
if ("STYLE" in opts) {
58+
let value = ctx.toRuntimeValue(opts["STYLE"]);
59+
if (value instanceof StringValue) {
60+
opt_values["style"] = value.value;
61+
}
62+
}
63+
if ("UNIT" in opts) {
64+
let value = ctx.toRuntimeValue(opts["UNIT"]);
65+
if (value instanceof StringValue) {
66+
opt_values["unit"] = value.value;
67+
}
68+
}
69+
70+
return new NumberValue(number.value, opt_values);
71+
}

experiments/stasm/third/impl/runtime.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,30 @@ export class StringValue extends RuntimeValue<string> {
3232
}
3333

3434
export class NumberValue extends RuntimeValue<number> {
35+
private opts: Intl.NumberFormatOptions;
36+
37+
constructor(value: number, opts: Intl.NumberFormatOptions = {}) {
38+
super(value);
39+
this.opts = opts;
40+
}
41+
3542
format(ctx: FormattingContext): string {
3643
// TODO(stasm): Cache NumberFormat.
37-
// TODO(stasm): Pass options.
38-
return new Intl.NumberFormat(ctx.locale).format(this.value);
44+
return new Intl.NumberFormat(ctx.locale, this.opts).format(this.value);
3945
}
4046
}
4147

4248
export class PluralValue extends RuntimeValue<number> {
49+
private opts: Intl.PluralRulesOptions;
50+
51+
constructor(value: number, opts: Intl.PluralRulesOptions = {}) {
52+
super(value);
53+
this.opts = opts;
54+
}
55+
4356
format(ctx: FormattingContext): string {
4457
// TODO(stasm): Cache PluralRules.
45-
// TODO(stasm): Pass options.
46-
let pr = new Intl.PluralRules(ctx.locale);
58+
let pr = new Intl.PluralRules(ctx.locale, this.opts);
4759
return pr.select(this.value);
4860
}
4961
}

experiments/stasm/third/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"scripts": {
1414
"example": "tsc && node example/index.js",
15-
"start": "tsc && (node example/index.js glossary; node example/index.js list; node example/index.js phrases)",
15+
"start": "tsc && (node example/index.js glossary; node example/index.js list; node example/index.js phrases; node example/index.js number)",
1616
"test": "echo \"Error: no test specified\" && exit 1"
1717
},
1818
"author": "Staś Małolepszy <[email protected]>",

0 commit comments

Comments
 (0)