Skip to content

Commit

Permalink
Refactor interface type representation in wast (#607)
Browse files Browse the repository at this point in the history
* Refactor interface type representation in `wast`

This commit updates the `wast` representation of interface types to
match more closely what `wasmparser` does. Previously `wast` primarily
used `ComponentTypeUse<'_, InterType<'_>>` for references and
`InterType<'_>` for definitions. This meant, though, that references
could not use primitives by-value. Additionally it also meant that the
parsing for `ComponentTypeUse` actually used `IndexOrRef` to parse
either `$t` or `(type $t)` but `ComponentTypeUse` is used for many other
constructs where it would not be appropriate for a bare index `$t` to be
parsed, for example this should not parse:

    (component
      (type $ty (module))
      (import "" (module $m $ty)))

This commit instead refactors all uses of
`ComponentTypeUse<'_, InterType<'_>>` to instead use a new
`InterTypeRef<'_>` construct. Additionally a `Primitive` was split out
from the existing `InterType<'_>` and added as a variant to the
`InterTypeRef<'_>` enum as well. This reflects the organization in the
`wasmparser` crate and means that primitive types can be used inline
instead of references and such.

Closes #600

* List an issue in FIXME annotations
  • Loading branch information
alexcrichton committed May 18, 2022
1 parent 5f3d593 commit cf92a1e
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 267 deletions.
2 changes: 0 additions & 2 deletions crates/wasmprinter/src/lib.rs
Expand Up @@ -2369,9 +2369,7 @@ impl Printer {
match ty {
InterfaceTypeRef::Primitive(ty) => self.print_primitive_type(ty),
InterfaceTypeRef::Type(idx) => {
self.result.push_str("(type ");
self.print_idx(&state.type_names, *idx)?;
self.result.push(')');
}
}

Expand Down
46 changes: 32 additions & 14 deletions crates/wast/src/component/binary.rs
Expand Up @@ -376,23 +376,31 @@ impl Encode for TypeField<'_> {
}
}

impl Encode for Primitive {
fn encode(&self, e: &mut Vec<u8>) {
match self {
Primitive::Unit => e.push(0x7f),
Primitive::Bool => e.push(0x7e),
Primitive::S8 => e.push(0x7d),
Primitive::U8 => e.push(0x7c),
Primitive::S16 => e.push(0x7b),
Primitive::U16 => e.push(0x7a),
Primitive::S32 => e.push(0x79),
Primitive::U32 => e.push(0x78),
Primitive::S64 => e.push(0x77),
Primitive::U64 => e.push(0x76),
Primitive::Float32 => e.push(0x75),
Primitive::Float64 => e.push(0x74),
Primitive::Char => e.push(0x73),
Primitive::String => e.push(0x72),
}
}
}

impl<'a> Encode for InterType<'a> {
fn encode(&self, e: &mut Vec<u8>) {
match self {
InterType::Unit => e.push(0x7f),
InterType::Bool => e.push(0x7e),
InterType::S8 => e.push(0x7d),
InterType::U8 => e.push(0x7c),
InterType::S16 => e.push(0x7b),
InterType::U16 => e.push(0x7a),
InterType::S32 => e.push(0x79),
InterType::U32 => e.push(0x78),
InterType::S64 => e.push(0x77),
InterType::U64 => e.push(0x76),
InterType::Float32 => e.push(0x75),
InterType::Float64 => e.push(0x74),
InterType::Char => e.push(0x73),
InterType::String => e.push(0x72),
InterType::Primitive(p) => p.encode(e),
InterType::Record(r) => r.encode(e),
InterType::Variant(v) => v.encode(e),
InterType::List(l) => l.encode(e),
Expand All @@ -406,6 +414,16 @@ impl<'a> Encode for InterType<'a> {
}
}

impl<'a> Encode for InterTypeRef<'a> {
fn encode(&self, e: &mut Vec<u8>) {
match self {
InterTypeRef::Primitive(p) => p.encode(e),
InterTypeRef::Ref(i) => i.encode(e),
InterTypeRef::Inline(_) => unreachable!("should be expanded by now"),
}
}
}

impl<'a> Encode for DefType<'a> {
fn encode(&self, e: &mut Vec<u8>) {
match self {
Expand Down
8 changes: 4 additions & 4 deletions crates/wast/src/component/deftype.rs
Expand Up @@ -101,7 +101,7 @@ pub struct ComponentFunctionType<'a> {
/// name resolution and a name for the custom `name` section.
pub params: Box<[ComponentFunctionParam<'a>]>,
/// The result type of a function.
pub result: ComponentTypeUse<'a, InterType<'a>>,
pub result: InterTypeRef<'a>,
}

impl<'a> Parse<'a> for ComponentFunctionType<'a> {
Expand All @@ -125,7 +125,7 @@ impl<'a> Parse<'a> for ComponentFunctionType<'a> {
})?
} else {
// If the result is omitted, use `unit`.
ComponentTypeUse::Inline(InterType::Unit)
InterTypeRef::Primitive(Primitive::Unit)
};
Ok(Self {
params: params.into(),
Expand All @@ -140,7 +140,7 @@ pub struct ComponentFunctionParam<'a> {
/// An optionally-specified name of this parameter
pub name: Option<&'a str>,
/// The type of the parameter.
pub type_: ComponentTypeUse<'a, InterType<'a>>,
pub type_: InterTypeRef<'a>,
}

/// A type for a nested module
Expand Down Expand Up @@ -306,7 +306,7 @@ impl<'a> From<TypeField<'a>> for InstanceTypeField<'a> {
#[derive(Debug, Clone)]
pub struct ValueType<'a> {
/// The type of the value.
pub value_type: ComponentTypeUse<'a, InterType<'a>>,
pub value_type: InterTypeRef<'a>,
}

impl<'a> Parse<'a> for ValueType<'a> {
Expand Down
69 changes: 41 additions & 28 deletions crates/wast/src/component/expand.rs
Expand Up @@ -247,9 +247,9 @@ impl<'a> Expander<'a> {

fn expand_func_ty(&mut self, ty: &mut ComponentFunctionType<'a>) {
for param in ty.params.iter_mut() {
self.expand_component_type_use(&mut param.type_);
self.expand_intertype_ref(&mut param.type_);
}
self.expand_component_type_use(&mut ty.result);
self.expand_intertype_ref(&mut ty.result);
}

fn expand_module_ty(&mut self, ty: &mut ModuleType<'a>) {
Expand Down Expand Up @@ -352,68 +352,81 @@ impl<'a> Expander<'a> {
}

fn expand_value_ty(&mut self, ty: &mut ValueType<'a>) {
self.expand_component_type_use(&mut ty.value_type);
self.expand_intertype_ref(&mut ty.value_type);
}

fn expand_intertype(&mut self, ty: &mut InterType<'a>) {
match ty {
InterType::Unit
| InterType::Bool
| InterType::S8
| InterType::U8
| InterType::S16
| InterType::U16
| InterType::S32
| InterType::U32
| InterType::S64
| InterType::U64
| InterType::Float32
| InterType::Float64
| InterType::Char
| InterType::String
| InterType::Flags(_)
| InterType::Enum(_) => {}
InterType::Primitive(_) | InterType::Flags(_) | InterType::Enum(_) => {}
InterType::Record(r) => {
for field in r.fields.iter_mut() {
self.expand_component_type_use(&mut field.type_);
self.expand_intertype_ref(&mut field.type_);
}
}
InterType::Variant(v) => {
for case in v.cases.iter_mut() {
self.expand_component_type_use(&mut case.type_);
self.expand_intertype_ref(&mut case.type_);
}
}
InterType::List(t) => {
self.expand_component_type_use(&mut t.element);
self.expand_intertype_ref(&mut t.element);
}
InterType::Tuple(t) => {
for field in t.fields.iter_mut() {
self.expand_component_type_use(field);
self.expand_intertype_ref(field);
}
}
InterType::Union(u) => {
for arm in u.arms.iter_mut() {
self.expand_component_type_use(arm);
self.expand_intertype_ref(arm);
}
}
InterType::Option(t) => {
self.expand_component_type_use(&mut t.element);
self.expand_intertype_ref(&mut t.element);
}
InterType::Expected(e) => {
self.expand_component_type_use(&mut e.ok);
self.expand_component_type_use(&mut e.err);
self.expand_intertype_ref(&mut e.ok);
self.expand_intertype_ref(&mut e.err);
}
}
}

fn expand_intertype_ref(&mut self, ty: &mut InterTypeRef<'a>) {
let inline = match ty {
InterTypeRef::Primitive(_) | InterTypeRef::Ref(_) => return,
InterTypeRef::Inline(inline) => {
mem::replace(inline, InterType::Primitive(Primitive::Unit))
}
};
// If this inline type has already been defined within this context
// then reuse the previously defined type to avoid injecting too many
// types into the type index space.
if let Some(idx) = inline.key().lookup(self) {
*ty = InterTypeRef::Ref(idx);
return;
}
// And if this type isn't already defined we append it to the index
// space with a fresh and unique name.
let span = Span::from_offset(0); // FIXME(#613): don't manufacture
let id = gensym::gen(span);
self.to_prepend.push(TypeField {
span,
id: Some(id),
name: None,
def: inline.into_def(),
});
let idx = Index::Id(id);
*ty = InterTypeRef::Ref(idx);
}

fn expand_component_type_use<T>(
&mut self,
item: &mut ComponentTypeUse<'a, T>,
) -> ItemRef<'a, kw::r#type>
where
T: TypeReference<'a>,
{
let span = Span::from_offset(0); // FIXME: don't manufacture
let span = Span::from_offset(0); // FIXME(#613): don't manufacture
let dummy = ComponentTypeUse::Ref(ItemRef {
idx: Index::Num(0, span),
kind: kw::r#type(span),
Expand Down

0 comments on commit cf92a1e

Please sign in to comment.