Skip to content

Commit 67634da

Browse files
committed
Implement let statement resolution.
This commit implements let-statement resolution, which includes: * Resolution of new expressions. * Resolution of access expressions. The resolution of new expressions is complicated as it has to perform type checks for the instantiation arguments; the logic of which is in the newly implemented `SubtypeChecker`, which operates solely off of WAC type information. Resolution now stores resolved "items" that have information attached about where they were sourced from (i.e. an import statement, an instantiation, etc.). Type information has been refactored (again, sorry) to hopefully make more sense and appear better in error messages. Additionally, the grammar was updated to support named instantiation arguments by identifier (and not just by strings). Error reporting has also been cleaned up to remove duplicated information. To support testing, a default `wat` feature allows for parsing component dependencies from local `wat` files. The CLI now supports passing the paths to known package dependencies (via the `--dep` option).
1 parent d1c1632 commit 67634da

187 files changed

Lines changed: 4756 additions & 1495 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: 111 additions & 95 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,28 @@ owo-colors = { workspace = true }
2929
serde = { workspace = true }
3030
serde_json = { workspace = true }
3131

32+
[features]
33+
default = []
34+
wat = ["wac-parser/wat"]
35+
3236
[workspace.dependencies]
33-
wac-parser = { path = "crates/wac-parser" }
37+
wac-parser = { path = "crates/wac-parser", default-features = false }
3438
wit-parser = "0.12.1"
35-
wasmparser = "0.113.3"
39+
wasmparser = "0.115.0"
3640
wit-component = "0.16.0"
3741
anyhow = "1.0.75"
38-
clap = { version = "4.4.3", features = ["derive"] }
39-
pest = "2.7.3"
40-
pest_derive = "2.7.3"
42+
clap = { version = "4.4.6", features = ["derive"] }
43+
pest = "2.7.4"
44+
pest_derive = "2.7.4"
4145
from-pest = "0.3.2"
4246
pest-ast = "0.3.4"
43-
semver = "1.0.18"
47+
semver = "1.0.20"
4448
pretty_env_logger = "0.5.0"
4549
log = "0.4.20"
46-
tokio = { version = "1.32.0", default-features = false, features = ["macros", "rt-multi-thread"] }
50+
tokio = { version = "1.33.0", default-features = false, features = ["macros", "rt-multi-thread"] }
4751
owo-colors = "3.5.0"
48-
indexmap = { version = "2.0.0", features = ["serde"] }
52+
indexmap = { version = "2.0.2", features = ["serde"] }
4953
id-arena = "2.2.1"
50-
serde = { version = "1.0.188", features = ["derive"] }
54+
serde = { version = "1.0.189", features = ["derive"] }
5155
serde_json = "1.0.107"
56+
wat = "1.0.77"

crates/wac-parser/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ serde = { workspace = true }
2424
wasmparser = { workspace = true }
2525
wit-parser = { workspace = true }
2626
wit-component = { workspace = true }
27+
wat = { workspace = true, optional = true }
28+
29+
[features]
30+
default = ["wat"]
2731

2832
[dev-dependencies]
2933
pretty_assertions = "1.4.0"

crates/wac-parser/src/ast.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ where
4343
}
4444

4545
/// Creates a new error with the given message, file path, and span.
46-
pub fn new_error_with_span(msg: impl fmt::Display, path: &Path, span: Span) -> anyhow::Error {
47-
let msg = msg.to_string();
46+
pub fn new_error_with_span(path: &Path, span: Span, msg: impl fmt::Display) -> anyhow::Error {
4847
let mut e = Error::new_from_span(
4948
ErrorVariant::CustomError::<Rule> {
50-
message: msg.clone(),
49+
message: msg.to_string(),
5150
},
5251
span,
5352
);
@@ -56,7 +55,15 @@ pub fn new_error_with_span(msg: impl fmt::Display, path: &Path, span: Span) -> a
5655
e = e.with_path(path)
5756
}
5857

59-
anyhow!(e).context(msg)
58+
let (line, column) = match e.line_col {
59+
pest::error::LineColLocation::Pos((l, c)) => (l, c),
60+
pest::error::LineColLocation::Span((l, c), _) => (l, c),
61+
};
62+
63+
anyhow!(format!(
64+
"{path}:{line}:{column}: {msg}\n\n{e}",
65+
path = path.display()
66+
))
6067
}
6168

6269
/// Used to indent output when displaying AST nodes.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ mod test {
103103

104104
roundtrip::<ExportStatement>(
105105
Rule::ExportStatement,
106-
"export new foo:bar { foo, bar: (new baz:qux {...}), baz: foo[\"baz\"].qux };",
107-
"export new foo:bar {\n foo,\n bar: (new baz:qux { ... }),\n baz: foo[\"baz\"].qux,\n};",
106+
"export new foo:bar { foo, \"bar\": (new baz:qux {...}), \"baz\": foo[\"baz\"].qux };",
107+
"export new foo:bar {\n foo,\n \"bar\": (new baz:qux { ... }),\n \"baz\": foo[\"baz\"].qux,\n};",
108108
)
109109
.unwrap();
110110
}

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

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::{
88
AstDisplay, Ident, Indenter, PackageName,
99
};
1010
use crate::parser::Rule;
11+
use pest::Span;
1112
use pest_ast::FromPest;
1213
use serde::Serialize;
1314
use std::fmt;
@@ -172,8 +173,8 @@ display!(InstantiationArgument);
172173
#[pest_ast(rule(Rule::NamedInstantiationArgument))]
173174
#[serde(rename_all = "camelCase")]
174175
pub struct NamedInstantiationArgument<'a> {
175-
/// The identifier in the argument.
176-
pub id: Ident<'a>,
176+
/// The name of the argument.
177+
pub name: InstantiationArgumentName<'a>,
177178
/// The colon in the argument.
178179
pub colon: Colon<'a>,
179180
/// The expression in the argument.
@@ -182,13 +183,46 @@ pub struct NamedInstantiationArgument<'a> {
182183

183184
impl AstDisplay for NamedInstantiationArgument<'_> {
184185
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
185-
write!(f, "{id}{colon} ", id = self.id, colon = self.colon)?;
186+
self.name.fmt(f, indenter)?;
187+
write!(f, "{colon} ", colon = self.colon)?;
186188
self.expr.fmt(f, indenter)
187189
}
188190
}
189191

190192
display!(NamedInstantiationArgument);
191193

194+
/// Represents the argument name in an instantiation argument in the AST.
195+
#[derive(Debug, Clone, Serialize, FromPest)]
196+
#[pest_ast(rule(Rule::InstantiationArgumentName))]
197+
#[serde(rename_all = "camelCase")]
198+
pub enum InstantiationArgumentName<'a> {
199+
/// The argument name is an identifier.
200+
Ident(Ident<'a>),
201+
/// The argument name is a string.
202+
String(super::String<'a>),
203+
}
204+
205+
impl<'a> InstantiationArgumentName<'a> {
206+
/// Gets the span of the instantiation argument name.
207+
pub fn span(&self) -> Span<'a> {
208+
match self {
209+
InstantiationArgumentName::Ident(ident) => ident.0,
210+
InstantiationArgumentName::String(string) => string.0,
211+
}
212+
}
213+
}
214+
215+
impl AstDisplay for InstantiationArgumentName<'_> {
216+
fn fmt(&self, f: &mut fmt::Formatter<'_>, _indenter: &mut Indenter) -> fmt::Result {
217+
match self {
218+
InstantiationArgumentName::Ident(ident) => ident.fmt(f, _indenter),
219+
InstantiationArgumentName::String(string) => string.fmt(f, _indenter),
220+
}
221+
}
222+
}
223+
224+
display!(InstantiationArgumentName);
225+
192226
/// Represents a nested expression in the AST.
193227
#[derive(Debug, Clone, Serialize, FromPest)]
194228
#[pest_ast(rule(Rule::NestedExpr))]
@@ -223,11 +257,21 @@ pub enum PostfixExpr<'a> {
223257
NamedAccess(NamedAccessExpr<'a>),
224258
}
225259

260+
impl<'a> PostfixExpr<'a> {
261+
/// Gets the span of the postfix expression.
262+
pub fn span(&self) -> pest::Span<'a> {
263+
match self {
264+
PostfixExpr::Access(access) => access.span(),
265+
PostfixExpr::NamedAccess(access) => access.span(),
266+
}
267+
}
268+
}
269+
226270
impl AstDisplay for PostfixExpr<'_> {
227271
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
228272
match self {
229273
PostfixExpr::Access(access) => access.fmt(f, indenter),
230-
PostfixExpr::NamedAccess(named_access) => named_access.fmt(f, indenter),
274+
PostfixExpr::NamedAccess(access) => access.fmt(f, indenter),
231275
}
232276
}
233277
}
@@ -245,6 +289,13 @@ pub struct AccessExpr<'a> {
245289
pub id: Ident<'a>,
246290
}
247291

292+
impl<'a> AccessExpr<'a> {
293+
/// Gets the span of the access expression.
294+
pub fn span(&self) -> Span<'a> {
295+
Span::new(self.dot.0.get_input(), self.dot.0.start(), self.id.0.end()).unwrap()
296+
}
297+
}
298+
248299
impl AstDisplay for AccessExpr<'_> {
249300
fn fmt(&self, f: &mut fmt::Formatter<'_>, _indenter: &mut Indenter) -> fmt::Result {
250301
write!(f, "{dot}{id}", dot = self.dot, id = self.id)
@@ -266,6 +317,18 @@ pub struct NamedAccessExpr<'a> {
266317
pub close: CloseBracket<'a>,
267318
}
268319

320+
impl<'a> NamedAccessExpr<'a> {
321+
/// Gets the span of the access expression.
322+
pub fn span(&self) -> Span<'a> {
323+
Span::new(
324+
self.open.0.get_input(),
325+
self.open.0.start(),
326+
self.close.0.end(),
327+
)
328+
.unwrap()
329+
}
330+
}
331+
269332
impl AstDisplay for NamedAccessExpr<'_> {
270333
fn fmt(&self, f: &mut fmt::Formatter<'_>, _indenter: &mut Indenter) -> fmt::Result {
271334
write!(
@@ -303,8 +366,8 @@ mod test {
303366

304367
roundtrip::<Expr>(
305368
Rule::Expr,
306-
"new foo:bar { foo, bar: (new baz:qux {...}), baz: foo[\"baz\"].qux }",
307-
"new foo:bar {\n foo,\n bar: (new baz:qux { ... }),\n baz: foo[\"baz\"].qux,\n}",
369+
"new foo:bar { foo, \"bar\": (new baz:qux {...}), \"baz\": foo[\"baz\"].qux }",
370+
"new foo:bar {\n foo,\n \"bar\": (new baz:qux { ... }),\n \"baz\": foo[\"baz\"].qux,\n}",
308371
)
309372
.unwrap();
310373
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ mod test {
7777

7878
roundtrip::<LetStatement>(
7979
Rule::LetStatement,
80-
"let x = new foo:bar { foo, bar: (new baz:qux {...}), baz: foo[\"baz\"].qux };",
81-
"let x = new foo:bar {\n foo,\n bar: (new baz:qux { ... }),\n baz: foo[\"baz\"].qux,\n};",
80+
"let x = new foo:bar { foo, \"bar\": (new baz:qux {...}), \"baz\": foo[\"baz\"].qux };",
81+
"let x = new foo:bar {\n foo,\n \"bar\": (new baz:qux { ... }),\n \"baz\": foo[\"baz\"].qux,\n};",
8282
)
8383
.unwrap();
8484
}

crates/wac-parser/src/parser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ mod pest {
101101
Self::NewExprBody => "new expression body",
102102
Self::InstantiationArgument => "instantiation argument",
103103
Self::NamedInstantiationArgument => "named instantiation argument",
104+
Self::InstantiationArgumentName => "instantiation argument name",
104105
Self::NestedExpr => "nested expression",
105106
Self::PostfixExpr => "postfix expression",
106107
Self::AccessExpr => "access expression",

0 commit comments

Comments
 (0)