Skip to content

Commit 3602006

Browse files
committed
Implement component encoding.
This giant commit implements encoding of resolved WAC documents, effectively enabling component composition. Changes to the grammar: * resource methods no longer accept references to function types (WIT compat). Changes to the AST: * The AST printer moved into the `ast` module. * Fixed `or` not printing correctly for printing lookahead failures. * Fixed segment spans in a package path not being calculated correctly. * Types now store their span; used in new resolution diagnostics. Changes to resolution: * The majority of the resolution logic has been refactored out into an `ast` submodule. * A check was added to ensure function result types do not contain a borrow. * There is now a package arena so that instantiations (and implicit imports) can keep track of the originating package for better diagnostic messages. * The value type enum was refactored such that borrows and owns of resources don't need allocations in the types arena (unless aliased with `type foo = borrow<x>`). * The `Item` struct and `ItemSource` enum were merged into a single `Item` enum. * Support for aliasing resources was added (e.g. `type r2 = r;`). * The `Resource` type no longer stores a collection of related methods as this *greatly* complicated merging of implicit imports; now resource methods are exported/imported directly in the exports/imports of an interface/world. * Consequently, merging of implicitly imported instances is now correctly implemented. * Subtype checking relating to resources has been improved so that the `ResourceMap` is no longer required. * Scope rules now better align with WIT; an interface or world may no longer reference top-level types. * Decoding binary packages now properly resolves resources and "used" types in interface and world definitions. Implementation of encoding: * Encoding of WIT subset of the grammar should match that of the existing WIT tooling; may be round-tripped with `wasm-tools component wit`. * Encoding of imports, instantiations, and exports should enable the output of actual WebAssembly compositions. CLI changes: * The `parse` command has been split into three different commands: * The `parse` command that outputs a JSON formatted AST. * The `resolve` command that outputs a JSON formatted resolved document. * The `encode` command that outputs with text or binary WebAssembly.
1 parent d949eeb commit 3602006

90 files changed

Lines changed: 6786 additions & 4676 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ keywords = ["webassembly", "wasm", "components", "component-model"]
1919
repository = "https://github.com/bytecodealliance/wac"
2020

2121
[dependencies]
22-
wac-parser = { workspace = true }
22+
wac-parser = { workspace = true, default-features = false}
2323
anyhow = { workspace = true }
2424
clap = { workspace = true }
2525
pretty_env_logger = { workspace = true }
@@ -28,6 +28,9 @@ tokio = { workspace = true }
2828
owo-colors = { workspace = true }
2929
serde = { workspace = true }
3030
serde_json = { workspace = true }
31+
wat = { workspace = true }
32+
wasmparser = { workspace = true }
33+
wasmprinter = { workspace = true }
3134

3235
[features]
3336
default = []
@@ -38,6 +41,9 @@ wac-parser = { path = "crates/wac-parser", default-features = false }
3841
wit-parser = "0.13.0"
3942
wasmparser = "0.116.1"
4043
wit-component = "0.18.0"
44+
wasm-encoder = "0.36.2"
45+
wasmprinter = "0.2.72"
46+
wasm-metadata = "0.10.11"
4147
anyhow = "1.0.75"
4248
clap = { version = "4.4.7", features = ["derive"] }
4349
semver = { version = "1.0.20", features = ["serde"] }

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ item-type-decl ::= resource-decl | type-decl
4646
resource-decl ::= 'resource' id '{' resource-item* '}'
4747
resource-item ::= constructor | method
4848
constructor ::= 'constructor' param-list
49-
method ::= id ':' 'static'? func-type-ref
49+
method ::= id ':' 'static'? func-type
5050
variant-decl ::= 'variant' id '{' variant-cases '}'
5151
variant-cases ::= variant-case (',' variant-case)* ','?
5252
variant-case ::= id ('(' type ')')?

crates/wac-parser/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ serde = { workspace = true }
2121
wasmparser = { workspace = true }
2222
wit-parser = { workspace = true }
2323
wit-component = { workspace = true }
24+
wasm-encoder = { workspace = true }
25+
wasm-metadata = { workspace = true }
2426
wat = { workspace = true, optional = true }
2527
owo-colors = { workspace = true }
2628

@@ -32,6 +34,7 @@ pretty_assertions = "1.4.0"
3234
pretty_env_logger = { workspace = true }
3335
rayon = "1.8.0"
3436
serde_json = { workspace = true }
37+
wasmprinter = { workspace = true }
3538

3639
[[test]]
3740
name = "parser"
@@ -40,3 +43,7 @@ harness = false
4043
[[test]]
4144
name = "resolution"
4245
harness = false
46+
47+
[[test]]
48+
name = "encoding"
49+
harness = false

crates/wac-parser/src/ast.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ mod export;
1111
mod expr;
1212
mod import;
1313
mod r#let;
14+
mod printer;
1415
mod r#type;
1516

1617
pub use export::*;
1718
pub use expr::*;
1819
pub use import::*;
20+
pub use printer::*;
1921
pub use r#let::*;
2022
pub use r#type::*;
2123

@@ -43,7 +45,7 @@ impl fmt::Display for Expected<'_> {
4345
write!(f, ", ")?;
4446
}
4547

46-
if i == self.expected.len() - 1 && self.count <= self.expected.len() {
48+
if i == self.count - 1 {
4749
write!(f, "or ")?;
4850
}
4951

@@ -306,7 +308,7 @@ macro_rules! display {
306308
($name:ident, $method:ident) => {
307309
impl std::fmt::Display for $name<'_> {
308310
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309-
let mut printer = crate::printer::DocumentPrinter::new(f, None);
311+
let mut printer = crate::ast::DocumentPrinter::new(f, None);
310312
printer.$method(self)
311313
}
312314
}

crates/wac-parser/src/ast/import.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl<'a> PackagePath<'a> {
9898
/// Iterates over the segments of the package path.
9999
pub fn segment_spans<'b>(&'b self) -> impl Iterator<Item = (&'a str, Span<'a>)> + 'b {
100100
self.segments.split('/').map(|s| {
101-
let start = s.as_ptr() as usize - self.name.as_ptr() as usize;
101+
let start = self.span.start + s.as_ptr() as usize - self.name.as_ptr() as usize;
102102
let end = start + s.len();
103103
(s, Span::from_span(self.span.source(), &(start..end)))
104104
})
Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,20 @@ impl<W: Write> DocumentPrinter<W> {
140140
/// Prints the given type.
141141
pub fn ty(&mut self, ty: &Type) -> std::fmt::Result {
142142
match ty {
143-
Type::U8 => write!(self.writer, "u8"),
144-
Type::S8 => write!(self.writer, "s8"),
145-
Type::U16 => write!(self.writer, "u16"),
146-
Type::S16 => write!(self.writer, "s16"),
147-
Type::U32 => write!(self.writer, "u32"),
148-
Type::S32 => write!(self.writer, "s32"),
149-
Type::U64 => write!(self.writer, "u64"),
150-
Type::S64 => write!(self.writer, "s64"),
151-
Type::Float32 => write!(self.writer, "float32"),
152-
Type::Float64 => write!(self.writer, "float64"),
153-
Type::Char => write!(self.writer, "char"),
154-
Type::Bool => write!(self.writer, "bool"),
155-
Type::String => write!(self.writer, "string"),
156-
Type::Tuple(types) => {
143+
Type::U8(_) => write!(self.writer, "u8"),
144+
Type::S8(_) => write!(self.writer, "s8"),
145+
Type::U16(_) => write!(self.writer, "u16"),
146+
Type::S16(_) => write!(self.writer, "s16"),
147+
Type::U32(_) => write!(self.writer, "u32"),
148+
Type::S32(_) => write!(self.writer, "s32"),
149+
Type::U64(_) => write!(self.writer, "u64"),
150+
Type::S64(_) => write!(self.writer, "s64"),
151+
Type::Float32(_) => write!(self.writer, "float32"),
152+
Type::Float64(_) => write!(self.writer, "float64"),
153+
Type::Char(_) => write!(self.writer, "char"),
154+
Type::Bool(_) => write!(self.writer, "bool"),
155+
Type::String(_) => write!(self.writer, "string"),
156+
Type::Tuple(types, _) => {
157157
write!(self.writer, "tuple<")?;
158158
for (i, ty) in types.iter().enumerate() {
159159
if i > 0 {
@@ -165,17 +165,17 @@ impl<W: Write> DocumentPrinter<W> {
165165

166166
write!(self.writer, ">")
167167
}
168-
Type::List(ty) => {
168+
Type::List(ty, _) => {
169169
write!(self.writer, "list<")?;
170170
self.ty(ty)?;
171171
write!(self.writer, ">")
172172
}
173-
Type::Option(ty) => {
173+
Type::Option(ty, _) => {
174174
write!(self.writer, "option<")?;
175175
self.ty(ty)?;
176176
write!(self.writer, ">")
177177
}
178-
Type::Result { ok, err } => match (ok, err) {
178+
Type::Result { ok, err, .. } => match (ok, err) {
179179
(None, None) => write!(self.writer, "result"),
180180
(None, Some(err)) => {
181181
write!(self.writer, "result<_, ")?;
@@ -195,7 +195,7 @@ impl<W: Write> DocumentPrinter<W> {
195195
write!(self.writer, ">")
196196
}
197197
},
198-
Type::Borrow(id) => {
198+
Type::Borrow(id, _) => {
199199
write!(self.writer, "borrow<{id}>", id = id.span.as_str())
200200
}
201201
Type::Ident(id) => write!(self.writer, "{id}", id = id.span.as_str()),
@@ -323,7 +323,7 @@ impl<W: Write> DocumentPrinter<W> {
323323
write!(self.writer, "static ")?;
324324
}
325325

326-
self.func_type_ref(&method.ty)?;
326+
self.func_type(&method.ty)?;
327327
write!(self.writer, ";")
328328
}
329329

0 commit comments

Comments
 (0)