WIT Syntax: `interface`
WIT + interface
Given the proposal to introduce a new top-level WIT syntax (i.e. worlds) for describing component types, it has become clear that *.wit documents are evolving to be able to express more than just a singular interface per file.
Additionally, while conceptually defining an interface per file may be desired (or even idiomatic) for many repositories it is inconvenient for use-cases where inlining N interfaces into a single *.wit file is preferable; For example tests become unwieldy and verbose if strewn across many files.
The interface syntax introduced below will enable such use-cases effectively loosening the currently imposed conventional organization of *.wit files.
See motivating comments.
From a component-model POV, an interface is WIT syntax for describing an instance type. As an example consider how the following interfaces might be modeled with WIT today:
// http-handler.wit
use { request, response, error } from http-types
handle-http-request: func(req: request) -> result<response, error>
// http-types.wit
record request {
// ...omitted
}
record response {
// ...omitted
}
variant error {
// ...omitted
}
Enabling the interface keyword will allow the refactor of these *.wit documents into a single file, e.g.:
// http.wit
interface http-handler {
use { request, response, error } from http-types
handle-http-request: func(req: request) -> result<response, error>
}
interface http-types {
record request {
// ...omitted
}
record response {
// ...omitted
}
variant error {
// ...omitted
}
}
Concretely, the structure of an interface is:
interface-item ::= `interface` id strlit? `{` interface-items* `}`
NOTE:
wit-itemrefers to the items that can be declared using WIT today.
This change makes a lot of sense to me, thanks for writing it up! Two follow-up comments:
In the BA tooling impl meeting last week, we discussed whether it was worth making the breaking change to always require interfaces to be wrapped with interface { ... } or whether to continue allowing the current "one implicit interface per file" syntax. Although avoiding churn is always preferable, in this case, it seems like it would create a long-term syntactic ambiguity hazard, since the parser starts out not knowing which "mode" it's in and then must infer this from the first few tokens of syntax. In the meeting, there seemed to be solid consensus it was worth it to make the breaking change, and thus always require interfaces to be wrapped in interface { ... }.
Another thing to consider is how URLs come in. Analogous to the now-merged #109, it seems like URL would be an optional second string after the id of an interface definition so you could, e.g., write: interface http-types "wasi:http/types" { ... } if you wanted and any component that imports or exports http-types would know to stick wasi:http/types as the URL of the import or export definition.
Thanks for capturing this @lukewagner! Completely agree. I updated the above grammar to reflect that.