From 8e4f125f08c524fb53ce6f798c4d2108ea8aa4f2 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Fri, 26 Sep 2025 18:52:36 -0700 Subject: [PATCH 1/9] make ValueTyped public, impl for &T --- crates/wasm-wave/src/value/convert.rs | 14 +++++++++++++- crates/wasm-wave/src/value/mod.rs | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index 6338f165e3..00ea62f88b 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -45,7 +45,7 @@ fn from_optional_wasm_type(ty: Option) -> Option> { }) } -trait ValueTyped { +pub trait ValueTyped { fn value_type() -> Type; } @@ -148,6 +148,17 @@ impl> From> for Value { } } +impl ValueTyped for &T { + fn value_type() -> Type { + T::value_type() + } +} +impl + Clone> From<&T> for Value { + fn from(value: &T) -> Self { + value.clone().into() + } +} + impl ValueTyped for Result { fn value_type() -> Type { Type::result(Some(T::value_type()), Some(U::value_type())) @@ -252,6 +263,7 @@ mod tests { (Some(1).into(), "some(1)"), (None::.into(), "none"), (Ok::(1).into(), "ok(1)"), + (Ok::<(), ()>(()).into(), "ok"), (Err::("oops".into()).into(), "err(\"oops\")"), ((1,).into(), "(1)"), ((1, "str", [9; 2]).into(), "(1, \"str\", [9, 9])"), diff --git a/crates/wasm-wave/src/value/mod.rs b/crates/wasm-wave/src/value/mod.rs index 8c8e9fe413..e31b5bef8a 100644 --- a/crates/wasm-wave/src/value/mod.rs +++ b/crates/wasm-wave/src/value/mod.rs @@ -1,6 +1,7 @@ //! Value enum for WAVE values. -mod convert; +#[allow(missing_docs)] +pub mod convert; #[cfg(test)] mod tests; mod ty; From 340e38bf373fa070211c0a26e992828e4d31bebe Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Mon, 29 Sep 2025 18:04:55 -0700 Subject: [PATCH 2/9] add ToRust trait, fix result unit type --- crates/wasm-wave/src/value/convert.rs | 116 +++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 13 deletions(-) diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index 00ea62f88b..20f048cd0c 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -48,9 +48,12 @@ fn from_optional_wasm_type(ty: Option) -> Option> { pub trait ValueTyped { fn value_type() -> Type; } +pub trait ToRust { + fn to_rust(x: &Value) -> Self; +} macro_rules! impl_primitives { - ($Self:ty, $(($case:ident, $ty:ty)),*) => { + ($Self:ty, $(($case:ident, $ty:ty, $unwrap:ident)),*) => { $( impl ValueTyped for $ty { fn value_type() -> Type { @@ -63,24 +66,30 @@ macro_rules! impl_primitives { Self(ValueEnum::$case(value)) } } + + impl ToRust for $ty { + fn to_rust(v: &Value) -> Self { + v.$unwrap() + } + } )* }; } impl_primitives!( Value, - (Bool, bool), - (S8, i8), - (S16, i16), - (S32, i32), - (S64, i64), - (U8, u8), - (U16, u16), - (U32, u32), - (U64, u64), - (F32, f32), - (F64, f64), - (Char, char) + (Bool, bool, unwrap_bool), + (S8, i8, unwrap_s8), + (S16, i16, unwrap_s16), + (S32, i32, unwrap_s32), + (S64, i64, unwrap_s64), + (U8, u8, unwrap_u8), + (U16, u16, unwrap_u16), + (U32, u32, unwrap_u32), + (U64, u64, unwrap_u64), + (F32, f32, unwrap_f32), + (F64, f64, unwrap_f64), + (Char, char, unwrap_char) ); impl ValueTyped for String { @@ -94,6 +103,11 @@ impl From for Value { Self(ValueEnum::String(value.into())) } } +impl ToRust for String { + fn to_rust(v: &Value) -> Self { + v.unwrap_string().into() + } +} impl ValueTyped for &str { fn value_type() -> Type { @@ -134,6 +148,11 @@ impl> From> for Value { Value::make_list(&ty, values).unwrap() } } +impl ToRust for Vec { + fn to_rust(v: &Value) -> Self { + v.unwrap_list().map(|x| T::to_rust(&x)).collect() + } +} impl ValueTyped for Option { fn value_type() -> Type { @@ -147,6 +166,11 @@ impl> From> for Value { Value::make_option(&ty, value.map(Into::into)).unwrap() } } +impl ToRust for Option { + fn to_rust(v: &Value) -> Self { + v.unwrap_option().map(|x| T::to_rust(&x)) + } +} impl ValueTyped for &T { fn value_type() -> Type { @@ -159,12 +183,42 @@ impl + Clone> From<&T> for Value { } } +impl ValueTyped for Result { + fn value_type() -> Type { + Type::result(Some(T::value_type()), None) + } +} +impl ValueTyped for Result<(), U> { + fn value_type() -> Type { + Type::result(None, Some(U::value_type())) + } +} impl ValueTyped for Result { fn value_type() -> Type { Type::result(Some(T::value_type()), Some(U::value_type())) } } +impl> From> for Value { + fn from(value: Result) -> Self { + let ty = Result::::value_type(); + let value = match value { + Ok(ok) => Ok(Some(ok.into())), + Err(()) => Err(None), + }; + Value::make_result(&ty, value).unwrap() + } +} +impl> From> for Value { + fn from(value: Result<(), U>) -> Self { + let ty = Result::<(), U>::value_type(); + let value = match value { + Ok(()) => Ok(None), + Err(err) => Err(Some(err.into())), + }; + Value::make_result(&ty, value).unwrap() + } +} impl, U: ValueTyped + Into> From> for Value { fn from(value: Result) -> Self { let ty = Result::::value_type(); @@ -175,6 +229,33 @@ impl, U: ValueTyped + Into> From Value::make_result(&ty, value).unwrap() } } +impl ToRust for Result { + fn to_rust(v: &Value) -> Self { + match v.unwrap_result() { + Ok(Some(ok)) => Ok(T::to_rust(&ok)), + Err(None) => Err(()), + _ => unreachable!(), + } + } +} +impl ToRust for Result<(), U> { + fn to_rust(v: &Value) -> Self { + match v.unwrap_result() { + Ok(None) => Ok(()), + Err(Some(err)) => Err(U::to_rust(&err)), + _ => unreachable!(), + } + } +} +impl ToRust for Result { + fn to_rust(v: &Value) -> Self { + match v.unwrap_result() { + Ok(Some(ok)) => Ok(T::to_rust(&ok)), + Err(Some(err)) => Err(U::to_rust(&err)), + _ => unreachable!(), + } + } +} macro_rules! impl_tuple { ($(($($var:ident),*)),*) => { @@ -196,6 +277,15 @@ macro_rules! impl_tuple { } } + impl<$($var: ToRust),*> ToRust for ($($var),*,) { + fn to_rust(v: &Value) -> Self { + let mut iter = v.unwrap_tuple(); + ($( + $var::to_rust(&iter.next().unwrap()), + )*) + } + } + )* }; } From 1fca1627bdb6f79eb469ba6578797abf201d1743 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Thu, 2 Oct 2025 11:36:02 -0700 Subject: [PATCH 3/9] update ToRust --- crates/wasm-wave/src/value/convert.rs | 77 ++++++++++++++++----------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index 20f048cd0c..0e8e649590 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -48,8 +48,8 @@ fn from_optional_wasm_type(ty: Option) -> Option> { pub trait ValueTyped { fn value_type() -> Type; } -pub trait ToRust { - fn to_rust(x: &Value) -> Self; +pub trait ToRust { + fn to_rust(&self) -> T; } macro_rules! impl_primitives { @@ -67,9 +67,9 @@ macro_rules! impl_primitives { } } - impl ToRust for $ty { - fn to_rust(v: &Value) -> Self { - v.$unwrap() + impl ToRust<$ty> for $Self { + fn to_rust(&self) -> $ty { + self.$unwrap() } } )* @@ -103,9 +103,9 @@ impl From for Value { Self(ValueEnum::String(value.into())) } } -impl ToRust for String { - fn to_rust(v: &Value) -> Self { - v.unwrap_string().into() +impl ToRust for Value { + fn to_rust(&self) -> String { + self.unwrap_string().into() } } @@ -148,9 +148,12 @@ impl> From> for Value { Value::make_list(&ty, values).unwrap() } } -impl ToRust for Vec { - fn to_rust(v: &Value) -> Self { - v.unwrap_list().map(|x| T::to_rust(&x)).collect() +impl ToRust> for Value +where + Value: ToRust, +{ + fn to_rust(&self) -> Vec { + self.unwrap_list().map(|x| x.to_rust()).collect() } } @@ -166,9 +169,12 @@ impl> From> for Value { Value::make_option(&ty, value.map(Into::into)).unwrap() } } -impl ToRust for Option { - fn to_rust(v: &Value) -> Self { - v.unwrap_option().map(|x| T::to_rust(&x)) +impl ToRust> for Value +where + Value: ToRust, +{ + fn to_rust(&self) -> Option { + self.unwrap_option().map(|x| x.to_rust()) } } @@ -229,29 +235,38 @@ impl, U: ValueTyped + Into> From Value::make_result(&ty, value).unwrap() } } -impl ToRust for Result { - fn to_rust(v: &Value) -> Self { - match v.unwrap_result() { - Ok(Some(ok)) => Ok(T::to_rust(&ok)), +impl ToRust> for Value +where + Value: ToRust, +{ + fn to_rust(&self) -> Result { + match self.unwrap_result() { + Ok(Some(ok)) => Ok(ok.to_rust()), Err(None) => Err(()), _ => unreachable!(), } } } -impl ToRust for Result<(), U> { - fn to_rust(v: &Value) -> Self { - match v.unwrap_result() { +impl ToRust> for Value +where + Value: ToRust, +{ + fn to_rust(&self) -> Result<(), U> { + match self.unwrap_result() { Ok(None) => Ok(()), - Err(Some(err)) => Err(U::to_rust(&err)), + Err(Some(err)) => Err(err.to_rust()), _ => unreachable!(), } } } -impl ToRust for Result { - fn to_rust(v: &Value) -> Self { - match v.unwrap_result() { - Ok(Some(ok)) => Ok(T::to_rust(&ok)), - Err(Some(err)) => Err(U::to_rust(&err)), +impl ToRust> for Value +where + Value: ToRust + ToRust, +{ + fn to_rust(&self) -> Result { + match self.unwrap_result() { + Ok(Some(ok)) => Ok(ok.to_rust()), + Err(Some(err)) => Err(err.to_rust()), _ => unreachable!(), } } @@ -277,11 +292,11 @@ macro_rules! impl_tuple { } } - impl<$($var: ToRust),*> ToRust for ($($var),*,) { - fn to_rust(v: &Value) -> Self { - let mut iter = v.unwrap_tuple(); + impl<$($var),*> ToRust<($($var),*,)> for Value where $( Value: ToRust<$var> ),* { + fn to_rust(&self) -> ($($var),*,) { + let mut iter = self.unwrap_tuple(); ($( - $var::to_rust(&iter.next().unwrap()), + ToRust::<$var>::to_rust(iter.next().unwrap().as_ref()), )*) } } From 75bcb1765ab1291f0ac9b39bbd3a6172b340c5c5 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Thu, 2 Oct 2025 21:55:41 -0700 Subject: [PATCH 4/9] add resource --- crates/wasm-wave/src/ast.rs | 6 ++++++ crates/wasm-wave/src/lex.rs | 4 ++++ crates/wasm-wave/src/parser.rs | 23 +++++++++++++++++++++++ crates/wasm-wave/src/untyped.rs | 1 + crates/wasm-wave/src/value/mod.rs | 25 +++++++++++++++++++++++++ crates/wasm-wave/src/value/ty.rs | 21 +++++++++++++++++++++ crates/wasm-wave/src/wasm/ty.rs | 9 +++++++++ crates/wasm-wave/src/wasm/val.rs | 18 ++++++++++++++++++ crates/wasm-wave/src/writer.rs | 12 ++++++++++++ 9 files changed, 119 insertions(+) diff --git a/crates/wasm-wave/src/ast.rs b/crates/wasm-wave/src/ast.rs index 91d989d7f0..ebb1903c65 100644 --- a/crates/wasm-wave/src/ast.rs +++ b/crates/wasm-wave/src/ast.rs @@ -470,4 +470,10 @@ pub enum NodeType { /// Flags /// Child nodes are flag Labels. Flags, + /// Resource + /// Child nodes are handle id and a optional borrow flag + Resource, + /// Borrow flag + /// Only appear under resource node + Borrow, } diff --git a/crates/wasm-wave/src/lex.rs b/crates/wasm-wave/src/lex.rs index 27d71d9c51..ed306f413b 100644 --- a/crates/wasm-wave/src/lex.rs +++ b/crates/wasm-wave/src/lex.rs @@ -40,6 +40,10 @@ pub enum Token { #[token(":")] Colon, + /// The `#` symbol + #[token("#")] + Sharp, + /// The `,` symbol #[token(",")] Comma, diff --git a/crates/wasm-wave/src/parser.rs b/crates/wasm-wave/src/parser.rs index dd17954b73..3550f4051d 100644 --- a/crates/wasm-wave/src/parser.rs +++ b/crates/wasm-wave/src/parser.rs @@ -81,6 +81,7 @@ impl<'source> Parser<'source> { Token::ParenOpen => self.parse_tuple()?, Token::BracketOpen => self.parse_list()?, Token::BraceOpen => self.parse_record_or_flags()?, + Token::Sharp => self.parse_resource()?, Token::LabelOrKeyword => match Keyword::decode(self.slice()) { Some(Keyword::True) => self.leaf_node(NodeType::BoolTrue), Some(Keyword::False) => self.leaf_node(NodeType::BoolFalse), @@ -99,6 +100,28 @@ impl<'source> Parser<'source> { }) } + fn parse_resource(&mut self) -> Result { + let start = self.span().start; + let mut children = Vec::new(); + match self.advance()? { + Token::BracketOpen => { + children.push(self.leaf_node(NodeType::Borrow)); + self.advance()?; + self.expect_token(Token::Number)?; + children.push(self.leaf_node(NodeType::Number)); + self.advance()?; + self.expect_token(Token::BracketClose)?; + } + Token::Number => children.push(self.leaf_node(NodeType::Number)), + _ => return Err(self.unexpected_token()), + } + Ok(Node::new( + NodeType::Resource, + start..self.span().end, + children, + )) + } + fn parse_tuple(&mut self) -> Result { let start = self.span().start; let children = self.parse_comma_separated_nodes(Token::ParenClose)?; diff --git a/crates/wasm-wave/src/untyped.rs b/crates/wasm-wave/src/untyped.rs index 8f57eb8747..4c76200ed8 100644 --- a/crates/wasm-wave/src/untyped.rs +++ b/crates/wasm-wave/src/untyped.rs @@ -184,6 +184,7 @@ fn fmt_node(f: &mut impl std::fmt::Write, node: &Node, src: &str) -> std::fmt::R } f.write_char('}') } + Resource | Borrow => todo!(), } } diff --git a/crates/wasm-wave/src/value/mod.rs b/crates/wasm-wave/src/value/mod.rs index e31b5bef8a..1dae781a97 100644 --- a/crates/wasm-wave/src/value/mod.rs +++ b/crates/wasm-wave/src/value/mod.rs @@ -58,6 +58,7 @@ pub(super) enum ValueEnum { Option(OptionValue), Result(ResultValue), Flags(Flags), + Resource(ResourceValue), } #[derive(Debug, Clone, PartialEq)] @@ -117,6 +118,13 @@ pub struct Flags { flags: Vec, } +#[derive(Debug, Clone, PartialEq)] +#[doc(hidden)] +pub struct ResourceValue { + handle: u32, + is_borrowed: bool, +} + macro_rules! impl_primitives { ($Self:ident, $(($case:ident, $ty:ty, $make:ident, $unwrap:ident)),*) => { $( @@ -157,6 +165,7 @@ impl WasmValue for Value { ValueEnum::Option(_) => WasmTypeKind::Option, ValueEnum::Result(_) => WasmTypeKind::Result, ValueEnum::Flags(_) => WasmTypeKind::Flags, + ValueEnum::Resource(_) => WasmTypeKind::Resource, } } @@ -316,6 +325,18 @@ impl WasmValue for Value { Ok(Self(ValueEnum::Flags(Flags { ty, flags }))) } + fn make_resource( + ty: &Self::Type, + handle: u32, + is_borrowed: bool, + ) -> Result { + ensure_type_kind(ty, WasmTypeKind::Resource)?; + Ok(Self(ValueEnum::Resource(ResourceValue { + handle, + is_borrowed, + }))) + } + fn unwrap_f32(&self) -> f32 { let val = *unwrap_val!(&self.0, ValueEnum::F32, "f32"); canonicalize_nan32(val) @@ -380,6 +401,10 @@ impl WasmValue for Value { .map(|idx| cow(flags.ty.flags[*idx].as_ref())), ) } + fn unwrap_resource(&self) -> (u32, bool) { + let res = unwrap_val!(&self.0, ValueEnum::Resource, "resource"); + (res.handle, res.is_borrowed) + } } fn cow(t: &T) -> Cow<'_, T> { diff --git a/crates/wasm-wave/src/value/ty.rs b/crates/wasm-wave/src/value/ty.rs index 94e269c298..d9df39bc40 100644 --- a/crates/wasm-wave/src/value/ty.rs +++ b/crates/wasm-wave/src/value/ty.rs @@ -18,6 +18,7 @@ pub(super) enum TypeEnum { Option(Arc), Result(Arc), Flags(Arc), + Resource(Arc), } #[allow(missing_docs)] @@ -135,6 +136,14 @@ impl Type { Some(Self(TypeEnum::Flags(Arc::new(FlagsType { flags })))) } + /// Returns a resource type with the given name. + pub fn resource(name: &str, is_borrowed: bool) -> Self { + Self(TypeEnum::Resource(Arc::new(ResourceType { + name: name.to_string(), + is_borrowed, + }))) + } + /// Returns a [`Type`] matching the given [`WasmType`]. Returns None if the /// given type is unsupported or otherwise invalid. pub fn from_wasm_type(ty: &impl WasmType) -> Option { @@ -194,6 +203,12 @@ pub struct FlagsType { pub(super) flags: Box<[Box]>, } +#[derive(Debug, PartialEq, Eq)] +pub struct ResourceType { + pub(super) name: String, + pub(super) is_borrowed: bool, +} + impl WasmType for Type { fn kind(&self) -> WasmTypeKind { match self.0 { @@ -207,6 +222,7 @@ impl WasmType for Type { TypeEnum::Option(_) => WasmTypeKind::Option, TypeEnum::Result(_) => WasmTypeKind::Result, TypeEnum::Flags(_) => WasmTypeKind::Flags, + TypeEnum::Resource(_) => WasmTypeKind::Resource, } } @@ -269,6 +285,11 @@ impl WasmType for Type { }; Box::new(flags.flags.iter().map(|name| name.as_ref().into())) } + + fn resource_type(&self) -> (&str, bool) { + let res = maybe_unwrap_type!(&self.0, TypeEnum::Resource).unwrap(); + (&res.name, res.is_borrowed) + } } impl std::fmt::Display for Type { diff --git a/crates/wasm-wave/src/wasm/ty.rs b/crates/wasm-wave/src/wasm/ty.rs index 1f3e47610f..021f4b5798 100644 --- a/crates/wasm-wave/src/wasm/ty.rs +++ b/crates/wasm-wave/src/wasm/ty.rs @@ -28,6 +28,7 @@ pub enum WasmTypeKind { Option, Result, Flags, + Resource, #[doc(hidden)] Unsupported, } @@ -57,6 +58,7 @@ impl std::fmt::Display for WasmTypeKind { WasmTypeKind::Option => "option", WasmTypeKind::Result => "result", WasmTypeKind::Flags => "flags", + WasmTypeKind::Resource => "resource", WasmTypeKind::Unsupported => "<>", }) } @@ -126,6 +128,13 @@ pub trait WasmType: Clone + Sized { fn flags_names(&self) -> Box> + '_> { unimplemented!() } + + /// Returns the resource name. + /// # Panics + /// Panics if the type is not implemented (the trait default). + fn resource_type(&self) -> (&str, bool) { + unimplemented!() + } } macro_rules! maybe_unwrap_type { diff --git a/crates/wasm-wave/src/wasm/val.rs b/crates/wasm-wave/src/wasm/val.rs index 127f6291ee..e44ad7b3db 100644 --- a/crates/wasm-wave/src/wasm/val.rs +++ b/crates/wasm-wave/src/wasm/val.rs @@ -180,6 +180,17 @@ pub trait WasmValue: Clone + Sized { unimplemented!() } + /// Returns a new WasmValue of the given type. + /// # Panics + /// Panics if the type is not implemented (the trait default). + fn make_resource( + ty: &Self::Type, + handle: u32, + is_borrow: bool, + ) -> Result { + unimplemented!() + } + /// Returns the underlying value of the WasmValue, panicing if it's the wrong type. /// # Panics /// Panics if `self` is not of the right type. @@ -316,6 +327,13 @@ pub trait WasmValue: Clone + Sized { fn unwrap_flags(&self) -> Box> + '_> { unimplemented!() } + + /// Returns the resource handle and whether it is a borrow resource or not. + /// # Panics + /// Panics if `self` is not of the right type. + fn unwrap_resource(&self) -> (u32, bool) { + unimplemented!() + } } macro_rules! unwrap_val { diff --git a/crates/wasm-wave/src/writer.rs b/crates/wasm-wave/src/writer.rs index 4233f359ed..415488cd87 100644 --- a/crates/wasm-wave/src/writer.rs +++ b/crates/wasm-wave/src/writer.rs @@ -168,6 +168,18 @@ impl Writer { self.write_str("}")?; Ok(()) } + WasmTypeKind::Resource => { + let (handle, is_borrowed) = val.unwrap_resource(); + self.write_str("#")?; + if is_borrowed { + self.write_str("<")?; + } + self.write_display(handle)?; + if is_borrowed { + self.write_str(">")?; + } + Ok(()) + } WasmTypeKind::Unsupported => panic!("unsupported value type"), } } From 635e14c69420348e81c2af3a2f66858a9c6cbe31 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Thu, 2 Oct 2025 22:16:45 -0700 Subject: [PATCH 5/9] add ToValue trait --- crates/wasm-wave/src/value/convert.rs | 72 +++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index 0e8e649590..e9e75253a1 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -51,6 +51,9 @@ pub trait ValueTyped { pub trait ToRust { fn to_rust(&self) -> T; } +pub trait ToValue { + fn to_value(&self) -> Value; +} macro_rules! impl_primitives { ($Self:ty, $(($case:ident, $ty:ty, $unwrap:ident)),*) => { @@ -72,6 +75,11 @@ macro_rules! impl_primitives { self.$unwrap() } } + impl ToValue for $ty { + fn to_value(&self) -> Value { + Value(ValueEnum::$case(*self)) + } + } )* }; } @@ -108,6 +116,11 @@ impl ToRust for Value { self.unwrap_string().into() } } +impl ToValue for String { + fn to_value(&self) -> Value { + Value(ValueEnum::String(self.to_owned().into())) + } +} impl ValueTyped for &str { fn value_type() -> Type { @@ -148,6 +161,13 @@ impl> From> for Value { Value::make_list(&ty, values).unwrap() } } +impl ToValue for Vec { + fn to_value(&self) -> Value { + let ty = Vec::::value_type(); + let values = self.iter().map(|x| x.to_value()); + Value::make_list(&ty, values).unwrap() + } +} impl ToRust> for Value where Value: ToRust, @@ -169,6 +189,12 @@ impl> From> for Value { Value::make_option(&ty, value.map(Into::into)).unwrap() } } +impl ToValue for Option { + fn to_value(&self) -> Value { + let ty = Option::::value_type(); + Value::make_option(&ty, self.as_ref().map(|x| x.to_value())).unwrap() + } +} impl ToRust> for Value where Value: ToRust, @@ -178,7 +204,7 @@ where } } -impl ValueTyped for &T { +/*impl ValueTyped for &T { fn value_type() -> Type { T::value_type() } @@ -187,7 +213,7 @@ impl + Clone> From<&T> for Value { fn from(value: &T) -> Self { value.clone().into() } -} +}*/ impl ValueTyped for Result { fn value_type() -> Type { @@ -235,6 +261,36 @@ impl, U: ValueTyped + Into> From Value::make_result(&ty, value).unwrap() } } +impl ToValue for Result { + fn to_value(&self) -> Value { + let ty = Result::::value_type(); + let value = match self { + Ok(ok) => Ok(Some(ok.to_value())), + Err(()) => Err(None), + }; + Value::make_result(&ty, value).unwrap() + } +} +impl ToValue for Result<(), U> { + fn to_value(&self) -> Value { + let ty = Result::<(), U>::value_type(); + let value = match self { + Ok(()) => Ok(None), + Err(err) => Err(Some(err.to_value())), + }; + Value::make_result(&ty, value).unwrap() + } +} +impl ToValue for Result { + fn to_value(&self) -> Value { + let ty = Result::::value_type(); + let value = match self { + Ok(ok) => Ok(Some(ok.to_value())), + Err(err) => Err(Some(err.to_value())), + }; + Value::make_result(&ty, value).unwrap() + } +} impl ToRust> for Value where Value: ToRust, @@ -291,6 +347,17 @@ macro_rules! impl_tuple { Value::make_tuple(&ty, vec![$($var),*]).unwrap() } } + #[allow(non_snake_case)] + impl<$($var: ValueTyped + ToValue),*> ToValue for ($($var),*,) { + fn to_value(&self) -> Value { + let ty = <($($var),*,)>::value_type(); + let ($($var),*,) = self; + $( + let $var = $var.to_value(); + )* + Value::make_tuple(&ty, vec![$($var),*]).unwrap() + } + } impl<$($var),*> ToRust<($($var),*,)> for Value where $( Value: ToRust<$var> ),* { fn to_rust(&self) -> ($($var),*,) { @@ -300,7 +367,6 @@ macro_rules! impl_tuple { )*) } } - )* }; } From 422bc2c978891d5a1a837c727480af581df53ce7 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Fri, 3 Oct 2025 11:18:55 -0700 Subject: [PATCH 6/9] fix --- crates/wasm-wave/src/value/convert.rs | 64 ++++++++++++++++----------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index e9e75253a1..e98a3b337a 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -133,12 +133,22 @@ impl<'a> From<&'a str> for Value { value.to_string().into() } } +impl<'a> ToValue for &'a str { + fn to_value(&self) -> Value { + self.to_string().to_value() + } +} impl ValueTyped for [T; N] { fn value_type() -> Type { Type::list(T::value_type()) } } +impl ValueTyped for [T] { + fn value_type() -> Type { + Type::list(T::value_type()) + } +} impl> From<[T; N]> for Value { fn from(values: [T; N]) -> Self { @@ -147,6 +157,13 @@ impl> From<[T; N]> for Value { Value::make_list(&ty, values).unwrap() } } +impl ToValue for [T] { + fn to_value(&self) -> Value { + let ty = <[T]>::value_type(); + let values = self.iter().map(|x| x.to_value()); + Value::make_list(&ty, values).unwrap() + } +} impl ValueTyped for Vec { fn value_type() -> Type { @@ -204,17 +221,11 @@ where } } -/*impl ValueTyped for &T { +impl ValueTyped for Result<(), ()> { fn value_type() -> Type { - T::value_type() + Type::result(None, None) } } -impl + Clone> From<&T> for Value { - fn from(value: &T) -> Self { - value.clone().into() - } -}*/ - impl ValueTyped for Result { fn value_type() -> Type { Type::result(Some(T::value_type()), None) @@ -231,32 +242,22 @@ impl ValueTyped for Result { } } -impl> From> for Value { - fn from(value: Result) -> Self { - let ty = Result::::value_type(); +impl, U: ValueTyped + Into> From> for Value { + fn from(value: Result) -> Self { + let ty = Result::::value_type(); let value = match value { Ok(ok) => Ok(Some(ok.into())), - Err(()) => Err(None), - }; - Value::make_result(&ty, value).unwrap() - } -} -impl> From> for Value { - fn from(value: Result<(), U>) -> Self { - let ty = Result::<(), U>::value_type(); - let value = match value { - Ok(()) => Ok(None), Err(err) => Err(Some(err.into())), }; Value::make_result(&ty, value).unwrap() } } -impl, U: ValueTyped + Into> From> for Value { - fn from(value: Result) -> Self { - let ty = Result::::value_type(); - let value = match value { - Ok(ok) => Ok(Some(ok.into())), - Err(err) => Err(Some(err.into())), +impl ToValue for Result<(), ()> { + fn to_value(&self) -> Value { + let ty = Result::<(), ()>::value_type(); + let value = match self { + Ok(()) => Ok(None), + Err(()) => Err(None), }; Value::make_result(&ty, value).unwrap() } @@ -291,6 +292,15 @@ impl ToValue for Result Value::make_result(&ty, value).unwrap() } } +impl ToRust> for Value { + fn to_rust(&self) -> Result<(), ()> { + match self.unwrap_result() { + Ok(None) => Ok(()), + Err(None) => Err(()), + _ => unreachable!(), + } + } +} impl ToRust> for Value where Value: ToRust, From 9528890c324f1e8bb20b549a56f548c1a3a7d594 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Tue, 7 Oct 2025 19:00:08 -0700 Subject: [PATCH 7/9] resource parsing --- crates/wasm-wave/src/ast.rs | 24 ++++++++++++++++++++++++ crates/wasm-wave/src/parser.rs | 14 ++++++++++++++ crates/wasm-wave/src/value/convert.rs | 3 ++- crates/wasm-wave/src/value/mod.rs | 15 +++++++++++++++ crates/wasm-wave/src/value/tests.rs | 14 ++++++++++++++ crates/wasm-wave/src/writer.rs | 4 ++-- 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/crates/wasm-wave/src/ast.rs b/crates/wasm-wave/src/ast.rs index ebb1903c65..c22fa19c03 100644 --- a/crates/wasm-wave/src/ast.rs +++ b/crates/wasm-wave/src/ast.rs @@ -227,6 +227,7 @@ impl Node { WasmTypeKind::Option => self.to_wasm_option(ty, src)?, WasmTypeKind::Result => self.to_wasm_result(ty, src)?, WasmTypeKind::Flags => self.to_wasm_flags(ty, src)?, + WasmTypeKind::Resource => self.to_wasm_resource(ty, src)?, other => { return Err( self.wasm_value_error(WasmValueError::UnsupportedType(other.to_string())) @@ -352,6 +353,29 @@ impl Node { V::make_option(ty, value).map_err(|err| self.wasm_value_error(err)) } + fn to_wasm_resource(&self, ty: &V::Type, src: &str) -> Result { + let (_, is_borrowed) = ty.resource_type(); + self.ensure_type(NodeType::Resource)?; + match self.children.as_slice() { + [handle] => { + let id = handle.as_number(src)?; + if is_borrowed { + return Err(self.error(ParserErrorKind::InvalidType)); + } + V::make_resource(ty, id, false).map_err(|err| self.wasm_value_error(err)) + } + [borrow, handle] => { + borrow.ensure_type(NodeType::Borrow)?; + if !is_borrowed { + return Err(self.error(ParserErrorKind::InvalidType)); + } + let id = handle.as_number(src)?; + V::make_resource(ty, id, true).map_err(|err| self.wasm_value_error(err)) + } + _ => Err(self.error(ParserErrorKind::InvalidType)), + } + } + fn to_wasm_result(&self, ty: &V::Type, src: &str) -> Result { let (ok_type, err_type) = ty.result_types().unwrap(); let value = match self.ty { diff --git a/crates/wasm-wave/src/parser.rs b/crates/wasm-wave/src/parser.rs index 3550f4051d..c14216c823 100644 --- a/crates/wasm-wave/src/parser.rs +++ b/crates/wasm-wave/src/parser.rs @@ -508,6 +508,20 @@ mod tests { ); } + #[test] + fn parse_resource() { + let ty = Type::resource("test_resource", false); + assert_eq!( + parse_value("#42", &ty), + Value::make_resource(&ty, 42, false).unwrap() + ); + let ty = Type::resource("resource", true); + assert_eq!( + parse_value("#[42]", &ty), + Value::make_resource(&ty, 42, true).unwrap() + ); + } + #[test] fn parse_record_reordering() { let ty = Type::record([("red", Type::S32), ("green", Type::CHAR)]).unwrap(); diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index e98a3b337a..ee579f6adb 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -431,6 +431,7 @@ mod tests { #[test] fn value_conversions() { + use crate::value::convert::ToValue; for (val, expect) in [ (1u8.into(), "1"), ((-123i8).into(), "-123"), @@ -444,7 +445,7 @@ mod tests { (Some(1).into(), "some(1)"), (None::.into(), "none"), (Ok::(1).into(), "ok(1)"), - (Ok::<(), ()>(()).into(), "ok"), + (Ok::<(), ()>(()).to_value(), "ok"), (Err::("oops".into()).into(), "err(\"oops\")"), ((1,).into(), "(1)"), ((1, "str", [9; 2]).into(), "(1, \"str\", [9, 9])"), diff --git a/crates/wasm-wave/src/value/mod.rs b/crates/wasm-wave/src/value/mod.rs index 1dae781a97..b85e8b4a14 100644 --- a/crates/wasm-wave/src/value/mod.rs +++ b/crates/wasm-wave/src/value/mod.rs @@ -331,6 +331,12 @@ impl WasmValue for Value { is_borrowed: bool, ) -> Result { ensure_type_kind(ty, WasmTypeKind::Resource)?; + let (_, expect_borrowed) = ty.resource_type(); + if expect_borrowed != is_borrowed { + return Err(WasmValueError::Other(format!( + "expect resource is_borrowed {expect_borrowed}, got value type is_borrowed {is_borrowed}" + ))); + } Ok(Self(ValueEnum::Resource(ResourceValue { handle, is_borrowed, @@ -560,6 +566,15 @@ fn check_type2(expected: &Type, val: &Value) -> Result<(), WasmValueError> { return wrong_value_type(); } } + (ValueEnum::Resource(resource), _) => { + if let TypeEnum::Resource(ty) = &expected.0 { + if ty.is_borrowed != resource.is_borrowed { + return wrong_value_type(); + } + } else { + return wrong_value_type(); + } + } (_, _) => return wrong_value_type(), }; Ok(()) diff --git a/crates/wasm-wave/src/value/tests.rs b/crates/wasm-wave/src/value/tests.rs index ba29cd8e16..085532bec5 100644 --- a/crates/wasm-wave/src/value/tests.rs +++ b/crates/wasm-wave/src/value/tests.rs @@ -89,6 +89,14 @@ fn option_round_trips() { test_value_round_trip(Value::make_option(&ty, None).unwrap()); } +#[test] +fn resource_round_trips() { + let ty = Type::resource("test", false); + test_value_round_trip(Value::make_resource(&ty, 42, false).unwrap()); + let ty = Type::resource("test", true); + test_value_round_trip(Value::make_resource(&ty, 42, true).unwrap()); +} + #[test] fn result_round_trips() { let no_payloads = Type::result(None, None); @@ -142,6 +150,12 @@ fn local_ty(val: &Value) -> Type { ValueEnum::Option(inner) => Type(TypeEnum::Option(inner.ty.clone())), ValueEnum::Result(inner) => Type(TypeEnum::Result(inner.ty.clone())), ValueEnum::Flags(inner) => Type(TypeEnum::Flags(inner.ty.clone())), + ValueEnum::Resource(inner) => Type(TypeEnum::Resource(std::sync::Arc::new( + crate::value::ty::ResourceType { + name: "".to_string(), + is_borrowed: inner.is_borrowed, + }, + ))), } } diff --git a/crates/wasm-wave/src/writer.rs b/crates/wasm-wave/src/writer.rs index 415488cd87..9c51fdc6cf 100644 --- a/crates/wasm-wave/src/writer.rs +++ b/crates/wasm-wave/src/writer.rs @@ -172,11 +172,11 @@ impl Writer { let (handle, is_borrowed) = val.unwrap_resource(); self.write_str("#")?; if is_borrowed { - self.write_str("<")?; + self.write_str("[")?; } self.write_display(handle)?; if is_borrowed { - self.write_str(">")?; + self.write_str("]")?; } Ok(()) } From 12d14969bb0577045d529fa5a09ccada3f0fc284 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Thu, 9 Oct 2025 16:33:59 -0700 Subject: [PATCH 8/9] fix --- crates/wasm-wave/src/value/convert.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/wasm-wave/src/value/convert.rs b/crates/wasm-wave/src/value/convert.rs index ee579f6adb..81bc38499e 100644 --- a/crates/wasm-wave/src/value/convert.rs +++ b/crates/wasm-wave/src/value/convert.rs @@ -48,6 +48,7 @@ fn from_optional_wasm_type(ty: Option) -> Option> { pub trait ValueTyped { fn value_type() -> Type; } +// ToRust is only defined for owned types pub trait ToRust { fn to_rust(&self) -> T; } From efecaa186fc3c3abe637bcad6234403b28d09322 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Mon, 10 Nov 2025 15:41:29 -0800 Subject: [PATCH 9/9] rename resource ast to handle --- crates/wasm-wave/src/ast.rs | 33 +++++------------- crates/wasm-wave/src/lex.rs | 5 +-- crates/wasm-wave/src/parser.rs | 37 ++++++-------------- crates/wasm-wave/src/untyped.rs | 2 +- crates/wasm-wave/src/value/mod.rs | 54 ++++++++--------------------- crates/wasm-wave/src/value/tests.rs | 15 ++++---- crates/wasm-wave/src/value/ty.rs | 20 +++++------ crates/wasm-wave/src/wasm/ty.rs | 8 ++--- crates/wasm-wave/src/wasm/val.rs | 10 ++---- crates/wasm-wave/src/writer.rs | 12 ++----- 10 files changed, 64 insertions(+), 132 deletions(-) diff --git a/crates/wasm-wave/src/ast.rs b/crates/wasm-wave/src/ast.rs index c22fa19c03..74c4348554 100644 --- a/crates/wasm-wave/src/ast.rs +++ b/crates/wasm-wave/src/ast.rs @@ -227,7 +227,7 @@ impl Node { WasmTypeKind::Option => self.to_wasm_option(ty, src)?, WasmTypeKind::Result => self.to_wasm_result(ty, src)?, WasmTypeKind::Flags => self.to_wasm_flags(ty, src)?, - WasmTypeKind::Resource => self.to_wasm_resource(ty, src)?, + WasmTypeKind::Handle => self.to_wasm_handle(ty, src)?, other => { return Err( self.wasm_value_error(WasmValueError::UnsupportedType(other.to_string())) @@ -353,24 +353,12 @@ impl Node { V::make_option(ty, value).map_err(|err| self.wasm_value_error(err)) } - fn to_wasm_resource(&self, ty: &V::Type, src: &str) -> Result { - let (_, is_borrowed) = ty.resource_type(); - self.ensure_type(NodeType::Resource)?; + fn to_wasm_handle(&self, _ty: &V::Type, src: &str) -> Result { + self.ensure_type(NodeType::Handle)?; match self.children.as_slice() { - [handle] => { - let id = handle.as_number(src)?; - if is_borrowed { - return Err(self.error(ParserErrorKind::InvalidType)); - } - V::make_resource(ty, id, false).map_err(|err| self.wasm_value_error(err)) - } - [borrow, handle] => { - borrow.ensure_type(NodeType::Borrow)?; - if !is_borrowed { - return Err(self.error(ParserErrorKind::InvalidType)); - } - let id = handle.as_number(src)?; - V::make_resource(ty, id, true).map_err(|err| self.wasm_value_error(err)) + [label] => { + let label = label.as_label(src)?; + Ok(V::make_handle(label.into())) } _ => Err(self.error(ParserErrorKind::InvalidType)), } @@ -494,10 +482,7 @@ pub enum NodeType { /// Flags /// Child nodes are flag Labels. Flags, - /// Resource - /// Child nodes are handle id and a optional borrow flag - Resource, - /// Borrow flag - /// Only appear under resource node - Borrow, + /// Handle + /// Child node is a opaque label. + Handle, } diff --git a/crates/wasm-wave/src/lex.rs b/crates/wasm-wave/src/lex.rs index ed306f413b..8ae8210803 100644 --- a/crates/wasm-wave/src/lex.rs +++ b/crates/wasm-wave/src/lex.rs @@ -12,7 +12,8 @@ pub type Lexer<'source> = logos::Lexer<'source, Token>; #[logos(error = Option)] #[logos(skip r"[ \t\n\r]+")] #[logos(skip r"//[^\n]*")] -#[logos(subpattern label_word = r"[a-z][a-z0-9]*|[A-Z][A-Z0-9]*")] +#[logos(subpattern first_label_word = r"[a-z][a-z0-9]*|[A-Z][A-Z0-9]*")] +#[logos(subpattern label_word = r"[a-z0-9]+|[A-Z0-9]+")] #[logos(subpattern char_escape = r#"\\['"tnr\\]|\\u\{[0-9a-fA-F]{1,6}\}"#)] pub enum Token { /// The `{` symbol @@ -54,7 +55,7 @@ pub enum Token { Number, /// A label or keyword - #[regex(r"%?(?&label_word)(-(?&label_word))*")] + #[regex(r"%?(?&first_label_word)(-(?&label_word))*")] LabelOrKeyword, /// A char literal diff --git a/crates/wasm-wave/src/parser.rs b/crates/wasm-wave/src/parser.rs index c14216c823..e1a80b897d 100644 --- a/crates/wasm-wave/src/parser.rs +++ b/crates/wasm-wave/src/parser.rs @@ -81,7 +81,7 @@ impl<'source> Parser<'source> { Token::ParenOpen => self.parse_tuple()?, Token::BracketOpen => self.parse_list()?, Token::BraceOpen => self.parse_record_or_flags()?, - Token::Sharp => self.parse_resource()?, + Token::Sharp => self.parse_handle()?, Token::LabelOrKeyword => match Keyword::decode(self.slice()) { Some(Keyword::True) => self.leaf_node(NodeType::BoolTrue), Some(Keyword::False) => self.leaf_node(NodeType::BoolFalse), @@ -100,26 +100,11 @@ impl<'source> Parser<'source> { }) } - fn parse_resource(&mut self) -> Result { + fn parse_handle(&mut self) -> Result { let start = self.span().start; - let mut children = Vec::new(); - match self.advance()? { - Token::BracketOpen => { - children.push(self.leaf_node(NodeType::Borrow)); - self.advance()?; - self.expect_token(Token::Number)?; - children.push(self.leaf_node(NodeType::Number)); - self.advance()?; - self.expect_token(Token::BracketClose)?; - } - Token::Number => children.push(self.leaf_node(NodeType::Number)), - _ => return Err(self.unexpected_token()), - } - Ok(Node::new( - NodeType::Resource, - start..self.span().end, - children, - )) + self.advance()?; + let label = self.parse_label()?; + Ok(Node::new(NodeType::Handle, start..self.span().end, [label])) } fn parse_tuple(&mut self) -> Result { @@ -510,15 +495,15 @@ mod tests { #[test] fn parse_resource() { - let ty = Type::resource("test_resource", false); + let ty = Type::handle("test_resource"); assert_eq!( - parse_value("#42", &ty), - Value::make_resource(&ty, 42, false).unwrap() + parse_value("#http-body-42", &ty), + Value::make_handle("http-body-42".into()) ); - let ty = Type::resource("resource", true); + let ty = Type::handle("resource"); assert_eq!( - parse_value("#[42]", &ty), - Value::make_resource(&ty, 42, true).unwrap() + parse_value("#borrow-http-body", &ty), + Value::make_handle("borrow-http-body".into()) ); } diff --git a/crates/wasm-wave/src/untyped.rs b/crates/wasm-wave/src/untyped.rs index 4c76200ed8..c7a700e30f 100644 --- a/crates/wasm-wave/src/untyped.rs +++ b/crates/wasm-wave/src/untyped.rs @@ -184,7 +184,7 @@ fn fmt_node(f: &mut impl std::fmt::Write, node: &Node, src: &str) -> std::fmt::R } f.write_char('}') } - Resource | Borrow => todo!(), + Handle => todo!(), } } diff --git a/crates/wasm-wave/src/value/mod.rs b/crates/wasm-wave/src/value/mod.rs index b85e8b4a14..5e95595cfc 100644 --- a/crates/wasm-wave/src/value/mod.rs +++ b/crates/wasm-wave/src/value/mod.rs @@ -58,7 +58,7 @@ pub(super) enum ValueEnum { Option(OptionValue), Result(ResultValue), Flags(Flags), - Resource(ResourceValue), + Handle(Box), } #[derive(Debug, Clone, PartialEq)] @@ -118,13 +118,6 @@ pub struct Flags { flags: Vec, } -#[derive(Debug, Clone, PartialEq)] -#[doc(hidden)] -pub struct ResourceValue { - handle: u32, - is_borrowed: bool, -} - macro_rules! impl_primitives { ($Self:ident, $(($case:ident, $ty:ty, $make:ident, $unwrap:ident)),*) => { $( @@ -165,7 +158,7 @@ impl WasmValue for Value { ValueEnum::Option(_) => WasmTypeKind::Option, ValueEnum::Result(_) => WasmTypeKind::Result, ValueEnum::Flags(_) => WasmTypeKind::Flags, - ValueEnum::Resource(_) => WasmTypeKind::Resource, + ValueEnum::Handle(_) => WasmTypeKind::Handle, } } @@ -197,6 +190,10 @@ impl WasmValue for Value { Self(ValueEnum::String(val.into())) } + fn make_handle(val: std::borrow::Cow) -> Self { + Self(ValueEnum::Handle(val.into())) + } + fn make_list( ty: &Self::Type, vals: impl IntoIterator, @@ -325,24 +322,6 @@ impl WasmValue for Value { Ok(Self(ValueEnum::Flags(Flags { ty, flags }))) } - fn make_resource( - ty: &Self::Type, - handle: u32, - is_borrowed: bool, - ) -> Result { - ensure_type_kind(ty, WasmTypeKind::Resource)?; - let (_, expect_borrowed) = ty.resource_type(); - if expect_borrowed != is_borrowed { - return Err(WasmValueError::Other(format!( - "expect resource is_borrowed {expect_borrowed}, got value type is_borrowed {is_borrowed}" - ))); - } - Ok(Self(ValueEnum::Resource(ResourceValue { - handle, - is_borrowed, - }))) - } - fn unwrap_f32(&self) -> f32 { let val = *unwrap_val!(&self.0, ValueEnum::F32, "f32"); canonicalize_nan32(val) @@ -358,6 +337,13 @@ impl WasmValue for Value { .as_ref() .into() } + + fn unwrap_handle(&self) -> std::borrow::Cow<'_, str> { + unwrap_val!(&self.0, ValueEnum::Handle, "handle") + .as_ref() + .into() + } + fn unwrap_list(&self) -> Box> + '_> { let list = unwrap_val!(&self.0, ValueEnum::List, "list"); Box::new(list.elements.iter().map(cow)) @@ -407,10 +393,6 @@ impl WasmValue for Value { .map(|idx| cow(flags.ty.flags[*idx].as_ref())), ) } - fn unwrap_resource(&self) -> (u32, bool) { - let res = unwrap_val!(&self.0, ValueEnum::Resource, "resource"); - (res.handle, res.is_borrowed) - } } fn cow(t: &T) -> Cow<'_, T> { @@ -566,15 +548,7 @@ fn check_type2(expected: &Type, val: &Value) -> Result<(), WasmValueError> { return wrong_value_type(); } } - (ValueEnum::Resource(resource), _) => { - if let TypeEnum::Resource(ty) = &expected.0 { - if ty.is_borrowed != resource.is_borrowed { - return wrong_value_type(); - } - } else { - return wrong_value_type(); - } - } + (ValueEnum::Handle(_), Type(TypeEnum::Handle(_))) => {} (_, _) => return wrong_value_type(), }; Ok(()) diff --git a/crates/wasm-wave/src/value/tests.rs b/crates/wasm-wave/src/value/tests.rs index 085532bec5..a0323a97a8 100644 --- a/crates/wasm-wave/src/value/tests.rs +++ b/crates/wasm-wave/src/value/tests.rs @@ -91,10 +91,10 @@ fn option_round_trips() { #[test] fn resource_round_trips() { - let ty = Type::resource("test", false); - test_value_round_trip(Value::make_resource(&ty, 42, false).unwrap()); - let ty = Type::resource("test", true); - test_value_round_trip(Value::make_resource(&ty, 42, true).unwrap()); + let ty = Type::handle("test"); + test_value_round_trip(Value::make_handle("test42".into())); + let ty = Type::handle("test"); + test_value_round_trip(Value::make_handle("test42".into())); } #[test] @@ -150,10 +150,9 @@ fn local_ty(val: &Value) -> Type { ValueEnum::Option(inner) => Type(TypeEnum::Option(inner.ty.clone())), ValueEnum::Result(inner) => Type(TypeEnum::Result(inner.ty.clone())), ValueEnum::Flags(inner) => Type(TypeEnum::Flags(inner.ty.clone())), - ValueEnum::Resource(inner) => Type(TypeEnum::Resource(std::sync::Arc::new( - crate::value::ty::ResourceType { - name: "".to_string(), - is_borrowed: inner.is_borrowed, + ValueEnum::Handle(inner) => Type(TypeEnum::Handle(std::sync::Arc::new( + crate::value::ty::HandleType { + name: inner.to_string(), }, ))), } diff --git a/crates/wasm-wave/src/value/ty.rs b/crates/wasm-wave/src/value/ty.rs index d9df39bc40..53710f9eb8 100644 --- a/crates/wasm-wave/src/value/ty.rs +++ b/crates/wasm-wave/src/value/ty.rs @@ -18,7 +18,7 @@ pub(super) enum TypeEnum { Option(Arc), Result(Arc), Flags(Arc), - Resource(Arc), + Handle(Arc), } #[allow(missing_docs)] @@ -136,11 +136,10 @@ impl Type { Some(Self(TypeEnum::Flags(Arc::new(FlagsType { flags })))) } - /// Returns a resource type with the given name. - pub fn resource(name: &str, is_borrowed: bool) -> Self { - Self(TypeEnum::Resource(Arc::new(ResourceType { + /// Returns a handle type with the given name. + pub fn handle(name: &str) -> Self { + Self(TypeEnum::Handle(Arc::new(HandleType { name: name.to_string(), - is_borrowed, }))) } @@ -204,9 +203,8 @@ pub struct FlagsType { } #[derive(Debug, PartialEq, Eq)] -pub struct ResourceType { +pub struct HandleType { pub(super) name: String, - pub(super) is_borrowed: bool, } impl WasmType for Type { @@ -222,7 +220,7 @@ impl WasmType for Type { TypeEnum::Option(_) => WasmTypeKind::Option, TypeEnum::Result(_) => WasmTypeKind::Result, TypeEnum::Flags(_) => WasmTypeKind::Flags, - TypeEnum::Resource(_) => WasmTypeKind::Resource, + TypeEnum::Handle(_) => WasmTypeKind::Handle, } } @@ -286,9 +284,9 @@ impl WasmType for Type { Box::new(flags.flags.iter().map(|name| name.as_ref().into())) } - fn resource_type(&self) -> (&str, bool) { - let res = maybe_unwrap_type!(&self.0, TypeEnum::Resource).unwrap(); - (&res.name, res.is_borrowed) + fn handle_type(&self) -> &str { + let res = maybe_unwrap_type!(&self.0, TypeEnum::Handle).unwrap(); + &res.name } } diff --git a/crates/wasm-wave/src/wasm/ty.rs b/crates/wasm-wave/src/wasm/ty.rs index 021f4b5798..0904101517 100644 --- a/crates/wasm-wave/src/wasm/ty.rs +++ b/crates/wasm-wave/src/wasm/ty.rs @@ -28,7 +28,7 @@ pub enum WasmTypeKind { Option, Result, Flags, - Resource, + Handle, #[doc(hidden)] Unsupported, } @@ -58,7 +58,7 @@ impl std::fmt::Display for WasmTypeKind { WasmTypeKind::Option => "option", WasmTypeKind::Result => "result", WasmTypeKind::Flags => "flags", - WasmTypeKind::Resource => "resource", + WasmTypeKind::Handle => "handle", WasmTypeKind::Unsupported => "<>", }) } @@ -129,10 +129,10 @@ pub trait WasmType: Clone + Sized { unimplemented!() } - /// Returns the resource name. + /// Returns the handle name. /// # Panics /// Panics if the type is not implemented (the trait default). - fn resource_type(&self) -> (&str, bool) { + fn handle_type(&self) -> &str { unimplemented!() } } diff --git a/crates/wasm-wave/src/wasm/val.rs b/crates/wasm-wave/src/wasm/val.rs index e44ad7b3db..b87182c3ca 100644 --- a/crates/wasm-wave/src/wasm/val.rs +++ b/crates/wasm-wave/src/wasm/val.rs @@ -183,11 +183,7 @@ pub trait WasmValue: Clone + Sized { /// Returns a new WasmValue of the given type. /// # Panics /// Panics if the type is not implemented (the trait default). - fn make_resource( - ty: &Self::Type, - handle: u32, - is_borrow: bool, - ) -> Result { + fn make_handle(label: Cow) -> Self { unimplemented!() } @@ -328,10 +324,10 @@ pub trait WasmValue: Clone + Sized { unimplemented!() } - /// Returns the resource handle and whether it is a borrow resource or not. + /// Returns the resource handle label. /// # Panics /// Panics if `self` is not of the right type. - fn unwrap_resource(&self) -> (u32, bool) { + fn unwrap_handle(&self) -> Cow<'_, str> { unimplemented!() } } diff --git a/crates/wasm-wave/src/writer.rs b/crates/wasm-wave/src/writer.rs index 9c51fdc6cf..8781a8c48e 100644 --- a/crates/wasm-wave/src/writer.rs +++ b/crates/wasm-wave/src/writer.rs @@ -168,16 +168,10 @@ impl Writer { self.write_str("}")?; Ok(()) } - WasmTypeKind::Resource => { - let (handle, is_borrowed) = val.unwrap_resource(); + WasmTypeKind::Handle => { + let label = val.unwrap_handle(); self.write_str("#")?; - if is_borrowed { - self.write_str("[")?; - } - self.write_display(handle)?; - if is_borrowed { - self.write_str("]")?; - } + self.write_display(label)?; Ok(()) } WasmTypeKind::Unsupported => panic!("unsupported value type"),