Skip to content

Commit

Permalink
Remove forward-compatibility promise and all reserved & private syntax (
Browse files Browse the repository at this point in the history
#883)

* Remove forwards compatibility from stability guarantee

* Drop reserved statements and expressions

* Drop private-use annotations

* Update tests

* Clarify that deprecation is not removal
  • Loading branch information
eemeli authored Sep 10, 2024
1 parent 01f2f40 commit 40db4e0
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 744 deletions.
34 changes: 4 additions & 30 deletions spec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,7 @@ Updates to this specification MUST NOT specify the use of a fallback value for a
that previously did not specify a fallback value.

Updates to this specification will not change the syntactical meaning
of any syntax defined in this specification except for that syntax marked as
"reserved for future standardization".

Updates to this specification will not assign any meaning to or change the syntactical
requirements for any private-use annotation.

Updates to this specification will not remove any reserved keywords or sigils.

Updates to this specification will not add any additional Unicode code points to
those in `reserved-annotation-start`.
of any syntax defined in this specification.

Updates to this specification will not remove any functions defined in the default registry.

Expand All @@ -114,13 +105,6 @@ defined in the default registry.
> differences in implementation or changes to locale data
> (such as due to the release of new CLDR versions).
Updates to this specification will not introduce message syntax that,
when parsed according to earlier versions of this specification,
would produce syntax or data model errors.
Messages that use syntax introduced in a future version of this specification
could produce resolution or message function errors
when formatted according to an earlier version of this specification.

Updates to this specification will only reserve, define, or require
function names or function option names
consisting of characters in the ranges a-z, A-Z, and 0-9.
Expand All @@ -137,29 +121,19 @@ based on this version being invalid.

> For example, existing interfaces or fields will not be removed.
Future versions of this specification will not introduce syntax that cannot be
represented by this version of the data model.

> For example, a future version could introduce a new keyword.
> The future version's data model would provide an interface for that keyword
> while this version of the data model would parse the value into
> the interface `UnsupportedStatement`.
> Both data models would be "valid" in their context,
> but this version's would be missing any functionality for the new statement type.
> [!IMPORTANT]
> This stability policy allows any of the following, non-exhaustive list, of changes
> in future versions of this specification:
> - Future versions may define new syntax and structures
> that would not be supported by this version of the specification.
> - Future versions may add additional structure or meaning to existing syntax.
> - Future versions may define new keywords.
> - Future versions may define annotations that use portions of the `reserved-annotation`
> syntax.
> - Future versions may make previously invalid messages valid.
> - Future versions may define additional functions in the default registry
> or may reserve the names of functions for the purposes of interoperability.
> - Future versions may define additional options to existing functions.
> - Future versions may define additional option values for existing options.
> - Future versions may deprecate functions, options, or option values.
> - Future versions may deprecate (but not remove) keywords, functions, options, or option values.
> - Future versions of this specification may introduce changes
> to the data model that would result in future data model representations
> not being valid for implementations of this version of the data model.
Expand Down
73 changes: 13 additions & 60 deletions spec/data-model/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ Implementations that expose APIs supporting the production, consumption, or tran
_message_ as a data structure are encouraged to use this data model.

This data model provides these capabilities:
- any MessageFormat 2 message (including future versions)
can be parsed into this representation
- any MessageFormat 2.0 message can be parsed into this representation
- this data model representation can be serialized as a well-formed
MessageFormat 2 message
- parsing a MessageFormat 2 message into a data model representation
MessageFormat 2.0 message
- parsing a MessageFormat 2.0 message into a data model representation
and then serializing it results in an equivalently functional message

This data model might also be used to:
Expand Down Expand Up @@ -98,21 +97,8 @@ The `name` does not include the initial `$` of the _variable_.
The `name` of an `InputDeclaration` MUST be the same
as the `name` in the `VariableRef` of its `VariableExpression` `value`.

An `UnsupportedStatement` represents a statement not supported by the implementation.
Its `keyword` is a non-empty string name (i.e. not including the initial `.`).
If not empty, the `body` is the "raw" value (i.e. escape sequences are not processed)
starting after the keyword and up to the first _expression_,
not including leading or trailing whitespace.
The non-empty `expressions` correspond to the trailing _expressions_ of the _reserved statement_.

> [!NOTE]
> Be aware that future versions of this specification
> might assign meaning to _reserved statement_ values.
> This would result in new interfaces being added to
> this data model.
```ts
type Declaration = InputDeclaration | LocalDeclaration | UnsupportedStatement;
type Declaration = InputDeclaration | LocalDeclaration;

interface InputDeclaration {
type: "input";
Expand All @@ -125,13 +111,6 @@ interface LocalDeclaration {
name: string;
value: Expression;
}

interface UnsupportedStatement {
type: "unsupported-statement";
keyword: string;
body?: string;
expressions: Expression[];
}
```

In a `SelectMessage`,
Expand Down Expand Up @@ -173,34 +152,26 @@ type Pattern = Array<string | Expression | Markup>;
type Expression =
| LiteralExpression
| VariableExpression
| FunctionExpression
| UnsupportedExpression;
| FunctionExpression;

interface LiteralExpression {
type: "expression";
arg: Literal;
annotation?: FunctionAnnotation | UnsupportedAnnotation;
function?: FunctionRef;
attributes: Attributes;
}

interface VariableExpression {
type: "expression";
arg: VariableRef;
annotation?: FunctionAnnotation | UnsupportedAnnotation;
function?: FunctionRef;
attributes: Attributes;
}

interface FunctionExpression {
type: "expression";
arg?: never;
annotation: FunctionAnnotation;
attributes: Attributes;
}

interface UnsupportedExpression {
type: "expression";
arg?: never;
annotation: UnsupportedAnnotation;
function: FunctionRef;
attributes: Attributes;
}
```
Expand All @@ -209,7 +180,7 @@ interface UnsupportedExpression {

The `Literal` and `VariableRef` correspond to the the _literal_ and _variable_ syntax rules.
When they are used as the `body` of an `Expression`,
they represent _expression_ values with no _annotation_.
they represent _expression_ values with no _function_.

`Literal` represents all literal values, both _quoted literal_ and _unquoted literal_.
The presence or absence of quotes is not preserved by the data model.
Expand All @@ -229,14 +200,14 @@ interface VariableRef {
}
```

A `FunctionAnnotation` represents a _function_ _annotation_.
A `FunctionRef` represents a _function_.
The `name` does not include the `:` starting sigil.

`Options` is a key-value mapping containing options,
and is used to represent the _annotation_ and _markup_ _options_.
and is used to represent the _function_ and _markup_ _options_.

```ts
interface FunctionAnnotation {
interface FunctionRef {
type: "function";
name: string;
options: Options;
Expand All @@ -245,31 +216,13 @@ interface FunctionAnnotation {
type Options = Map<string, Literal | VariableRef>;
```

An `UnsupportedAnnotation` represents a
_private-use annotation_ not supported by the implementation or a _reserved annotation_.
The `source` is the "raw" value (i.e. escape sequences are not processed),
including the starting sigil.

When parsing the syntax of a _message_ that includes a _private-use annotation_
supported by the implementation,
the implementation SHOULD represent it in the data model
using an interface appropriate for the semantics and meaning
that the implementation attaches to that _annotation_.

```ts
interface UnsupportedAnnotation {
type: "unsupported-annotation";
source: string;
}
```

## Markup

A `Markup` object has a `kind` of either `"open"`, `"standalone"`, or `"close"`,
each corresponding to _open_, _standalone_, and _close_ _markup_.
The `name` in these does not include the starting sigils `#` and `/`
or the ending sigil `/`.
The `options` for markup use the same key-value mapping as `FunctionAnnotation`.
The `options` for markup use the same key-value mapping as `FunctionRef`.

```ts
interface Markup {
Expand Down
18 changes: 5 additions & 13 deletions spec/data-model/message.dtd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!ELEMENT message (
(declaration | unsupportedStatement)*,
(declaration)*,
(pattern | (selectors,variant+))
)>

Expand All @@ -10,12 +10,6 @@
name NMTOKEN #REQUIRED
>

<!ELEMENT unsupportedStatement (expression)+>
<!ATTLIST unsupportedStatement
keyword CDATA #REQUIRED
body CDATA #IMPLIED
>

<!ELEMENT selectors (expression)+>
<!ELEMENT variant (key+,pattern)>
<!ELEMENT key (#PCDATA)>
Expand All @@ -24,23 +18,21 @@
<!ELEMENT pattern (#PCDATA | expression | markup)*>

<!ELEMENT expression (
((literal | variable), (functionAnnotation | unsupportedAnnotation)?, attribute*) |
((functionAnnotation | unsupportedAnnotation), attribute*)
((literal | variable), function?, attribute*) |
(function, attribute*)
)>

<!ELEMENT literal (#PCDATA)>

<!ELEMENT variable (EMPTY)>
<!ATTLIST variable name NMTOKEN #REQUIRED>

<!ELEMENT functionAnnotation (option)*>
<!ATTLIST functionAnnotation name NMTOKEN #REQUIRED>
<!ELEMENT function (option)*>
<!ATTLIST function name NMTOKEN #REQUIRED>

<!ELEMENT option (literal | variable)>
<!ATTLIST option name NMTOKEN #REQUIRED>

<!ELEMENT unsupportedAnnotation (#PCDATA)>

<!ELEMENT attribute (literal)?>
<!ATTLIST attribute name NMTOKEN #REQUIRED>

Expand Down
76 changes: 7 additions & 69 deletions spec/data-model/message.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}
},

"function-annotation": {
"function": {
"type": "object",
"properties": {
"type": { "const": "function" },
Expand All @@ -45,65 +45,17 @@
},
"required": ["type", "name"]
},
"unsupported-annotation": {
"type": "object",
"properties": {
"type": { "const": "unsupported-annotation" },
"source": { "type": "string" }
},
"required": ["type", "source"]
},
"annotation": {
"oneOf": [
{ "$ref": "#/$defs/function-annotation" },
{ "$ref": "#/$defs/unsupported-annotation" }
]
},

"literal-expression": {
"type": "object",
"properties": {
"type": { "const": "expression" },
"arg": { "$ref": "#/$defs/literal" },
"annotation": { "$ref": "#/$defs/annotation" },
"attributes": { "$ref": "#/$defs/attributes" }
},
"required": ["type", "arg"]
},
"variable-expression": {
"type": "object",
"properties": {
"type": { "const": "expression" },
"arg": { "$ref": "#/$defs/variable" },
"annotation": { "$ref": "#/$defs/annotation" },
"attributes": { "$ref": "#/$defs/attributes" }
},
"required": ["type", "arg"]
},
"function-expression": {
"type": "object",
"properties": {
"type": { "const": "expression" },
"annotation": { "$ref": "#/$defs/function-annotation" },
"attributes": { "$ref": "#/$defs/attributes" }
},
"required": ["type", "annotation"]
},
"unsupported-expression": {
"expression": {
"type": "object",
"properties": {
"type": { "const": "expression" },
"annotation": { "$ref": "#/$defs/unsupported-annotation" },
"arg": { "$ref": "#/$defs/literal-or-variable" },
"function": { "$ref": "#/$defs/function" },
"attributes": { "$ref": "#/$defs/attributes" }
},
"required": ["type", "annotation"]
},
"expression": {
"oneOf": [
{ "$ref": "#/$defs/literal-expression" },
{ "$ref": "#/$defs/variable-expression" },
{ "$ref": "#/$defs/function-expression" },
{ "$ref": "#/$defs/unsupported-expression" }
{ "required": ["type", "arg"] },
{ "required": ["type", "function"] }
]
},

Expand Down Expand Up @@ -148,26 +100,12 @@
},
"required": ["type", "name", "value"]
},
"unsupported-statement": {
"type": "object",
"properties": {
"type": { "const": "unsupported-statement" },
"keyword": { "type": "string" },
"body": { "type": "string" },
"expressions": {
"type": "array",
"items": { "$ref": "#/$defs/expression" }
}
},
"required": ["type", "keyword", "expressions"]
},
"declarations": {
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/$defs/input-declaration" },
{ "$ref": "#/$defs/local-declaration" },
{ "$ref": "#/$defs/unsupported-statement" }
{ "$ref": "#/$defs/local-declaration" }
]
}
},
Expand Down
Loading

0 comments on commit 40db4e0

Please sign in to comment.