Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested interfaces #372

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions design/mvp/WIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ would correspond to:
)
```

An `interface` can contain [`use`][use] statements, [type][types] definitions,
An `interface` can contain [`use`][use] and [`nest`][nest] statements, [type][types] definitions,
and [function][functions] definitions. For example:

```wit
Expand All @@ -136,7 +136,7 @@ interface types {
}
```

More information about [`use`][use] and [types] are described below, but this
More information about [`use`][use], [`nest`][nest], and [types] are described below, but this
is an example of a collection of items within an `interface`. All items defined
in an `interface`, including [`use`][use] items, are considered as exports from
the interface. This means that types can further be used from the interface by
Expand Down Expand Up @@ -660,6 +660,73 @@ world w2 {
> configure that a `use`'d interface is a particular import or a particular
> export.

## Nesting WIT interfaces
[nest]: #nesting-wit-interfaces
Interfaces can also contain other interfaces via the `nest` keyword.
With the `nest` keyword, one can reference other interfaces in the same package, foreign packages, or define anonymous interfaces inline.

```wit
package local:example;

interface foo {
...
}

interface top {
nest foo;
nest foreign:pkg/bar;
baz: interface {
...
}
Comment on lines +678 to +680
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Syntactically I might bikeshed this as nest baz { ... } perhaps? (to keep the word "nest" around it and not have too too many keywords)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah funny, that's what I had originally, and changed it to this after discussing a bit with @lukewagner. Personally, I'm not so attached to either, but his thoughts I believe were that the syntax as I have it currently would match how anonymous interfaces in worlds are expressed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also be ok with nest a: interface { ... } but I do think that we'll want nest somewhere in here to align with the other nest syntaxes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see both arguments, but while writing nest a: interface { ... }; is more symmetric with nest foo:bar/baz; writing a: interface { ... }; is more symmetric with a: func() -> blah; (in interfaces) and import a: interface { ... }; (in worlds). Since the reason for having nest in the first place is because <interfacename>; is lexically ambiguous (due to the : inside <interfacename>) and also looks odd, and since with a: interface { ... }; there's no lexical ambiguity and it looks roughly like what it means in worlds, my vague preference is to go with the latter symmetry.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left as is for now, though I noticed Luke was using semicolons for anonymous interfaces, while we weren't using them before... not sure if people feel one way or another about that, but I don't think it's ambiguous to leave them out, similarly to how records are handled.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I hadn't noticed the precedent for anonymous interfaces in worlds was to leave off the semicolon, so I'd go with that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coincidentally, working through the proposed additions in #308 made me realize that a semicolon after anonymous interfaces (in both interfaces and worlds) is probably a good idea for long-term future compatibility. See e.g. the code examples in this comment where I think you end up wanting the ; always.

}
```

Each of these forms of nesting interfaces are encoded as:

```wasm
(component
(type (;0;)
(component
(type (;0;)
(instance
... `types from foo`
)
)
(export "local:example/foo" (type 0))
)
)
(export (;1;) "foo" (type 0))
(type (;2;)
(component
(type (;0;)
(instance
(type (;0;)
(instance
... `types from foo`
)
)
(export "local:example/foo" (instance (type 0)))
(type (;1;)
(instance
... `types from foreign:pkg/bar`
)
)
(export "foreign:pkg/bar" (instance (type 1)))
(type (;2;)
(instance
... `types from baz`
)
)
(export "baz" (instance (type 2)))
)
)
(export "local:example/top (type 1))
)
)
(export (;3;) "top" (type 2))
)
```

## WIT Functions
[functions]: #wit-functions

Expand Down Expand Up @@ -1106,6 +1173,7 @@ interface-items ::= gate interface-definition
interface-definition ::= typedef-item
| use-item
| func-item
| nest-item

typedef-item ::= resource-item
| variant-items
Expand All @@ -1128,6 +1196,9 @@ named-type-list ::= ϵ
| named-type ( ',' named-type )*

named-type ::= id ':' ty

nest-item ::= gate nest use-path ';'
| id: interface-item
```


Expand Down
Loading