Skip to content

Commit d1c1632

Browse files
authored
Merge pull request #5 from peterhuene/projection
Implement package resolution.
2 parents 4de8fc3 + 1c7f753 commit d1c1632

57 files changed

Lines changed: 4946 additions & 1630 deletions

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: 111 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: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
[package]
22
name = "wac"
3+
description = "A tool for encoding and decoding WebAssembly compositions."
4+
version = { workspace = true }
5+
edition = { workspace = true }
6+
authors = { workspace = true }
7+
license = { workspace = true }
8+
categories = { workspace = true }
9+
keywords = { workspace = true }
10+
repository = { workspace = true }
11+
12+
[workspace.package]
313
version = "0.1.0"
414
edition = "2021"
515
authors = ["Peter Huene <peter@huene.dev>"]
6-
description = "A tool for encoding and decoding WebAssembly compositions."
716
license = "Apache-2.0 WITH LLVM-exception"
8-
documentation = "https://docs.rs/wac"
917
categories = ["wasm"]
1018
keywords = ["webassembly", "wasm", "components", "component-model"]
1119
repository = "https://github.com/bytecodealliance/wac"
@@ -23,6 +31,9 @@ serde_json = { workspace = true }
2331

2432
[workspace.dependencies]
2533
wac-parser = { path = "crates/wac-parser" }
34+
wit-parser = "0.12.1"
35+
wasmparser = "0.113.3"
36+
wit-component = "0.16.0"
2637
anyhow = "1.0.75"
2738
clap = { version = "4.4.3", features = ["derive"] }
2839
pest = "2.7.3"

crates/wac-parser/Cargo.toml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
[package]
22
name = "wac-parser"
3-
version = "0.1.0"
4-
edition = "2021"
5-
authors = ["Peter Huene <peter@huene.dev>"]
63
description = "A library for encoding and decoding WebAssembly compositions."
7-
license = "Apache-2.0 WITH LLVM-exception"
8-
documentation = "https://docs.rs/wac-parser"
9-
categories = ["wasm"]
10-
keywords = ["webassembly", "wasm", "components", "component-model"]
11-
repository = "https://github.com/bytecodealliance/wac"
4+
version = { workspace = true }
5+
edition = { workspace = true }
6+
authors = { workspace = true }
7+
license = { workspace = true }
8+
categories = { workspace = true }
9+
keywords = { workspace = true }
10+
repository = { workspace = true }
1211

1312
[dependencies]
1413
anyhow = { workspace = true }
@@ -22,6 +21,9 @@ log = { workspace = true }
2221
indexmap = { workspace = true }
2322
id-arena = { workspace = true }
2423
serde = { workspace = true }
24+
wasmparser = { workspace = true }
25+
wit-parser = { workspace = true }
26+
wit-component = { workspace = true }
2527

2628
[dev-dependencies]
2729
pretty_assertions = "1.4.0"

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

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,35 +109,50 @@ display!(WithClause);
109109
pub struct PackagePath<'a> {
110110
/// The name of the package.
111111
pub name: PackageName<'a>,
112-
/// The path into the package.
113-
pub path: Vec<(Slash<'a>, Ident<'a>)>,
114-
/// The version of the package.
112+
/// The path segments.
113+
pub segments: Vec<(Slash<'a>, Ident<'a>)>,
114+
/// The optional version of the package.
115115
pub version: Option<(At<'a>, PackageVersion<'a>)>,
116116
}
117117

118118
impl PackagePath<'_> {
119119
/// Calculates the span of the package path.
120120
pub fn span(&self) -> Span {
121-
let span = self.name.parts.first().unwrap().0;
121+
let span = self.name.span();
122122
let end = if let Some((_, version)) = &self.version {
123123
version.0.end()
124-
} else if let Some((_, path)) = self.path.last() {
125-
path.0.end()
126124
} else {
127-
span.end()
125+
self.segments_span().end()
128126
};
129127

130128
Span::new(span.get_input(), span.start(), end).unwrap()
131129
}
130+
131+
/// Returns the string representation of the package path.
132+
pub fn as_str(&self) -> &str {
133+
self.span().as_str()
134+
}
135+
136+
/// Gets the span of just the path segments.
137+
pub fn segments_span(&self) -> Span {
138+
let (_, first) = self.segments.first().unwrap();
139+
let (_, last) = self.segments.last().unwrap();
140+
Span::new(first.0.get_input(), first.0.start(), last.0.end()).unwrap()
141+
}
142+
143+
/// Gets the path segments as a string.
144+
pub fn segments(&self) -> &str {
145+
self.segments_span().as_str()
146+
}
132147
}
133148

134149
impl AstDisplay for PackagePath<'_> {
135150
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
136151
self.name.fmt(f, indenter)?;
137152

138-
for (slash, part) in &self.path {
153+
for (slash, segment) in &self.segments {
139154
write!(f, "{slash}")?;
140-
part.fmt(f, indenter)?;
155+
segment.fmt(f, indenter)?;
141156
}
142157

143158
if let Some((at, version)) = &self.version {
@@ -160,6 +175,20 @@ pub struct PackageName<'a> {
160175
pub parts: Vec<Ident<'a>>,
161176
}
162177

178+
impl PackageName<'_> {
179+
/// Gets the span of the package name.
180+
pub fn span(&self) -> Span {
181+
let span = self.parts.first().unwrap().0;
182+
let end = self.parts.last().map(|i| i.0.end()).unwrap();
183+
Span::new(span.get_input(), span.start(), end).unwrap()
184+
}
185+
186+
/// Gets the package name as a string.
187+
pub fn as_str(&self) -> &str {
188+
self.span().as_str()
189+
}
190+
}
191+
163192
impl AstDisplay for PackageName<'_> {
164193
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
165194
for (i, part) in self.parts.iter().enumerate() {

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

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::parser::Rule;
1414
use pest::Span;
1515
use pest_ast::FromPest;
1616
use serde::Serialize;
17-
use std::{borrow::Cow, fmt};
17+
use std::fmt;
1818

1919
/// Represents a type statement in the AST.
2020
#[derive(Debug, Clone, Serialize, FromPest)]
@@ -1142,7 +1142,7 @@ pub struct UseItems<'a> {
11421142
/// The opening brace of the statement.
11431143
pub open: OpenBrace<'a>,
11441144
/// The items being used.
1145-
pub list: Vec<Ident<'a>>,
1145+
pub list: Vec<UseItem<'a>>,
11461146
/// The closing brace of the use items.
11471147
pub close: CloseBrace<'a>,
11481148
}
@@ -1166,6 +1166,51 @@ impl AstDisplay for UseItems<'_> {
11661166

11671167
display!(UseItems);
11681168

1169+
/// Represents an item being used in a use statement in the AST.
1170+
#[derive(Debug, Clone, Serialize, FromPest)]
1171+
#[pest_ast(rule(Rule::UseItem))]
1172+
#[serde(rename_all = "camelCase")]
1173+
pub struct UseItem<'a> {
1174+
/// The identifier of the item.
1175+
pub id: Ident<'a>,
1176+
/// The optional as clause of the item.
1177+
pub as_clause: std::option::Option<UseAsClause<'a>>,
1178+
}
1179+
1180+
impl AstDisplay for UseItem<'_> {
1181+
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
1182+
self.id.fmt(f, indenter)?;
1183+
1184+
if let Some(as_clause) = &self.as_clause {
1185+
write!(f, " {as_clause}")?;
1186+
}
1187+
1188+
Ok(())
1189+
}
1190+
}
1191+
1192+
display!(UseItem);
1193+
1194+
/// Represents an as clause in a use statement in the AST.
1195+
#[derive(Debug, Clone, Serialize, FromPest)]
1196+
#[pest_ast(rule(Rule::UseAsClause))]
1197+
#[serde(rename_all = "camelCase")]
1198+
pub struct UseAsClause<'a> {
1199+
/// The `as` keyword.
1200+
pub keyword: As<'a>,
1201+
/// The identifier of the as clause.
1202+
pub id: Ident<'a>,
1203+
}
1204+
1205+
impl AstDisplay for UseAsClause<'_> {
1206+
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
1207+
write!(f, "{keyword} ", keyword = self.keyword)?;
1208+
self.id.fmt(f, indenter)
1209+
}
1210+
}
1211+
1212+
display!(UseAsClause);
1213+
11691214
/// Represents a use path in the AST.
11701215
#[derive(Debug, Clone, Serialize, FromPest)]
11711216
#[pest_ast(rule(Rule::UsePath))]
@@ -1524,11 +1569,11 @@ pub enum WorldRef<'a> {
15241569
}
15251570

15261571
impl<'a> WorldRef<'a> {
1527-
/// Gets the full name of the world ref.
1528-
pub fn name(&self) -> Cow<'a, str> {
1572+
/// Gets the name of the world being referred to.
1573+
pub fn name(&self) -> &str {
15291574
match self {
1530-
Self::Ident(id) => Cow::Borrowed(id.as_str()),
1531-
Self::Path(path) => Cow::Owned(path.to_string()),
1575+
Self::Ident(id) => id.as_str(),
1576+
Self::Path(path) => path.as_str(),
15321577
}
15331578
}
15341579

crates/wac-parser/src/parser.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ mod pest {
7070

7171
Self::UseStatement => "use statement",
7272
Self::UseItems => "use items",
73+
Self::UseItem => "use item",
74+
Self::UseAsClause => "use as clause",
7375
Self::UsePath => "use path",
7476

7577
Self::InterfaceBody => "interface body",

0 commit comments

Comments
 (0)