Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2879325

Browse files
committed
(third) Add RuntimeValue.match()
1 parent 3cb74f1 commit 2879325

File tree

5 files changed

+63
-55
lines changed

5 files changed

+63
-55
lines changed

experiments/stasm/third/example/example_list.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {test} from "tap";
22
import {FormattingContext} from "../impl/context.js";
3-
import {Argument, Message, Parameter} from "../impl/model.js";
3+
import {Argument, Message, Parameter, VariantKey} from "../impl/model.js";
44
import {REGISTRY} from "../impl/registry.js";
55
import {
66
formatMessage,
@@ -40,6 +40,10 @@ class ListValue<T> extends RuntimeValue<Array<T>> {
4040
let lf = new Intl.ListFormat(ctx.locale, this.opts);
4141
yield* lf.formatToParts(this.value);
4242
}
43+
44+
match(ctx: FormattingContext, key: VariantKey): boolean {
45+
return false;
46+
}
4347
}
4448

4549
REGISTRY["PLURAL_LEN"] = function (

experiments/stasm/third/example/example_opaque.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {test} from "tap";
22
import {FormattingContext} from "../impl/context.js";
3-
import {Message} from "../impl/model.js";
3+
import {Message, VariantKey} from "../impl/model.js";
44
import {formatToParts, OpaquePart, RuntimeValue} from "../impl/runtime.js";
55

66
// We want to pass it into the translation and get it back out unformatted, in
@@ -16,6 +16,10 @@ class WrappedValue extends RuntimeValue<SomeUnstringifiableClass> {
1616
*formatToParts(ctx: FormattingContext): IterableIterator<OpaquePart> {
1717
yield {type: "opaque", value: this.value};
1818
}
19+
20+
match(ctx: FormattingContext, key: VariantKey): boolean {
21+
return false;
22+
}
1923
}
2024

2125
test("Pass an opaque instance as a variable", (tap) => {

experiments/stasm/third/impl/context.ts

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
import {
2-
IntegerLiteral,
3-
Message,
4-
Parameter,
5-
PatternElement,
6-
Selector,
7-
StringLiteral,
8-
Variant,
9-
} from "./model.js";
1+
import {Message, Parameter, PatternElement, Selector, StringLiteral, Variant} from "./model.js";
102
import {REGISTRY} from "./registry.js";
11-
import {BooleanValue, NumberValue, PluralValue, RuntimeValue, StringValue} from "./runtime.js";
3+
import {BooleanValue, NumberValue, RuntimeValue, StringValue} from "./runtime.js";
124

135
// Resolution context for a single formatMessage() call.
146

@@ -64,27 +56,22 @@ export class FormattingContext {
6456
}
6557

6658
selectVariant(variants: Array<Variant>, selectors: Array<Selector>): Variant {
67-
interface ResolvedSelector {
68-
value: RuntimeValue<unknown>;
69-
default: string;
70-
}
59+
let selector_values: Array<RuntimeValue<unknown>> = [];
60+
let selector_defaults: Array<StringLiteral> = [];
7161

72-
let resolved_selectors: Array<ResolvedSelector> = [];
7362
for (let selector of selectors) {
7463
switch (selector.expr.type) {
7564
case "VariableReference": {
76-
resolved_selectors.push({
77-
value: this.vars[selector.expr.name],
78-
default: selector.default.value,
79-
});
65+
let value = this.vars[selector.expr.name];
66+
selector_values.push(value);
67+
selector_defaults.push(selector.default);
8068
break;
8169
}
8270
case "FunctionCall": {
8371
let callable = REGISTRY[selector.expr.name];
84-
resolved_selectors.push({
85-
value: callable(this, selector.expr.args, selector.expr.opts),
86-
default: selector.default.value,
87-
});
72+
let value = callable(this, selector.expr.args, selector.expr.opts);
73+
selector_values.push(value);
74+
selector_defaults.push(selector.default);
8875
break;
8976
}
9077
default:
@@ -93,37 +80,18 @@ export class FormattingContext {
9380
}
9481
}
9582

96-
function matches_corresponding_selector(key: StringLiteral | IntegerLiteral, idx: number) {
97-
let selector = resolved_selectors[idx];
98-
switch (key.type) {
99-
case "StringLiteral": {
100-
if (key.value === selector.value.value) {
101-
return true;
102-
}
103-
break;
104-
}
105-
case "IntegerLiteral": {
106-
let num = parseInt(key.value);
107-
if (selector.value instanceof NumberValue) {
108-
if (num === selector.value.value) {
109-
return true;
110-
}
111-
} else if (selector.value instanceof PluralValue) {
112-
if (key.value === selector.value.value || num === selector.value.count) {
113-
return true;
114-
}
115-
}
116-
break;
117-
}
118-
}
119-
120-
return key.value === selector.default;
121-
}
122-
12383
for (let variant of variants) {
12484
// When keys is an empty array, every() always returns true. This is
12585
// used single-variant messages to return their only variant.
126-
if (variant.keys.every(matches_corresponding_selector)) {
86+
if (
87+
variant.keys.every(
88+
(key, idx) =>
89+
// Key matches corresponding selector value…
90+
selector_values[idx].match(this, key) ||
91+
// … or the corresponding default.
92+
key.value === selector_defaults[idx].value
93+
)
94+
) {
12795
return variant;
12896
}
12997
}

experiments/stasm/third/impl/model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ export interface Selector {
1717
}
1818

1919
export interface Variant {
20-
keys: Array<StringLiteral | IntegerLiteral>;
20+
keys: Array<VariantKey>;
2121
value: Array<PatternElement>;
2222
}
2323

24+
export type VariantKey = StringLiteral | IntegerLiteral;
2425
export type PatternElement = StringLiteral | VariableReference | FunctionCall;
2526

2627
export interface FunctionCall {

experiments/stasm/third/impl/runtime.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {FormattingContext} from "./context.js";
2-
import {Message, PatternElement} from "./model.js";
2+
import {Message, PatternElement, VariantKey} from "./model.js";
33

44
export interface FormattedPart {
55
type: string;
@@ -26,6 +26,7 @@ export abstract class RuntimeValue<T> {
2626

2727
abstract formatToString(ctx: FormattingContext): string;
2828
abstract formatToParts(ctx: FormattingContext): IterableIterator<FormattedPart | OpaquePart>;
29+
abstract match(ctx: FormattingContext, key: VariantKey): boolean;
2930
}
3031

3132
export class StringValue extends RuntimeValue<string> {
@@ -36,6 +37,10 @@ export class StringValue extends RuntimeValue<string> {
3637
*formatToParts(ctx: FormattingContext): IterableIterator<FormattedPart> {
3738
yield {type: "literal", value: this.value};
3839
}
40+
41+
match(ctx: FormattingContext, key: VariantKey): boolean {
42+
return this.value === key.value;
43+
}
3944
}
4045

4146
export class NumberValue extends RuntimeValue<number> {
@@ -54,6 +59,13 @@ export class NumberValue extends RuntimeValue<number> {
5459
*formatToParts(ctx: FormattingContext): IterableIterator<FormattedPart> {
5560
yield* new Intl.NumberFormat(ctx.locale, this.opts).formatToParts(this.value);
5661
}
62+
63+
match(ctx: FormattingContext, key: VariantKey): boolean {
64+
if (key.type === "IntegerLiteral") {
65+
return this.value === parseInt(key.value);
66+
}
67+
return false;
68+
}
5769
}
5870

5971
export class PluralValue extends RuntimeValue<Intl.LDMLPluralRule> {
@@ -71,6 +83,17 @@ export class PluralValue extends RuntimeValue<Intl.LDMLPluralRule> {
7183
*formatToParts(ctx: FormattingContext): IterableIterator<FormattedPart> {
7284
throw new TypeError("PluralValue is not formattable.");
7385
}
86+
87+
match(ctx: FormattingContext, key: VariantKey): boolean {
88+
switch (key.type) {
89+
case "StringLiteral": {
90+
return this.value === key.value;
91+
}
92+
case "IntegerLiteral": {
93+
return this.count === parseInt(key.value);
94+
}
95+
}
96+
}
7497
}
7598

7699
export class BooleanValue extends RuntimeValue<boolean> {
@@ -81,6 +104,10 @@ export class BooleanValue extends RuntimeValue<boolean> {
81104
*formatToParts(ctx: FormattingContext): IterableIterator<FormattedPart> {
82105
throw new TypeError("BooleanValue is not formattable to parts.");
83106
}
107+
108+
match(ctx: FormattingContext, key: VariantKey): boolean {
109+
throw new TypeError("BooleanValue cannot match.");
110+
}
84111
}
85112

86113
export class PatternValue extends RuntimeValue<Array<PatternElement>> {
@@ -93,6 +120,10 @@ export class PatternValue extends RuntimeValue<Array<PatternElement>> {
93120
yield* value.formatToParts(ctx);
94121
}
95122
}
123+
124+
match(ctx: FormattingContext, key: VariantKey): boolean {
125+
throw new TypeError("PatternValue cannot match.");
126+
}
96127
}
97128

98129
export function formatMessage(

0 commit comments

Comments
 (0)