usecrate::component::*; usecrate::core; usecrate::gensym; usecrate::kw; usecrate::token::Id; usecrate::token::{Index, Span}; use std::collections::HashMap; use std::mem;
/// Performs an AST "expansion" pass over the component fields provided. /// /// This expansion is intended to desugar the AST from various parsed constructs /// to bits and bobs amenable for name resolution as well as binary encoding. /// For example `(import "i" (func))` is split into a type definition followed by /// the import referencing that type definition. /// /// Most forms of AST expansion happen in this file and afterwards the AST will /// be handed to the name resolution pass which will convert `Index::Id` to /// `Index::Num` wherever it's found. pubfn expand(fields: &mut Vec<ComponentField<'_>>) {
Expander::default().expand_component_fields(fields)
}
impl<'a> From<AnyType<'a>> for ComponentTypeDecl<'a> { fn from(t: AnyType<'a>) -> Self { match t {
AnyType::Core(t) => Self::CoreType(t),
AnyType::Component(t) => Self::Type(t),
}
}
}
impl<'a> From<AnyType<'a>> for InstanceTypeDecl<'a> { fn from(t: AnyType<'a>) -> Self { match t {
AnyType::Core(t) => Self::CoreType(t),
AnyType::Component(t) => Self::Type(t),
}
}
}
impl<'a> From<AnyType<'a>> for ComponentField<'a> { fn from(t: AnyType<'a>) -> Self { match t {
AnyType::Core(t) => Self::CoreType(t),
AnyType::Component(t) => Self::Type(t),
}
}
}
#[derive(Default)] struct Expander<'a> { /// Fields, during processing, which should be prepended to the /// currently-being-processed field. This should always be empty after /// processing is complete.
types_to_prepend: Vec<AnyType<'a>>,
component_fields_to_prepend: Vec<ComponentField<'a>>,
/// Fields that are appended to the end of the module once everything has /// finished.
component_fields_to_append: Vec<ComponentField<'a>>,
}
impl<'a> Expander<'a> { fn expand_component_fields(&mutself, fields: &mut Vec<ComponentField<'a>>) { letmut cur = 0; while cur < fields.len() { self.expand_field(&mut fields[cur]); let amt = self.types_to_prepend.len() + self.component_fields_to_prepend.len();
fields.splice(cur..cur, self.component_fields_to_prepend.drain(..));
fields.splice(cur..cur, self.types_to_prepend.drain(..).map(Into::into));
cur += 1 + amt;
}
fields.append(&mutself.component_fields_to_append);
}
fn expand_decls<T>(&mutself, decls: &mut Vec<T>, expand: fn(&mutSelf, &mut T)) where
T: From<AnyType<'a>>,
{ letmut cur = 0; while cur < decls.len() {
expand(self, &mut decls[cur]);
assert!(self.component_fields_to_prepend.is_empty());
assert!(self.component_fields_to_append.is_empty()); let amt = self.types_to_prepend.len();
decls.splice(cur..cur, self.types_to_prepend.drain(..).map(From::from));
cur += 1 + amt;
}
}
let id = gensym::fill(field.span, &mut field.id); let index = Index::Id(id); match &field.def {
CoreTypeDef::Def(_) => {}
CoreTypeDef::Module(t) => t.key().insert(self, index),
}
}
// Note that this is a custom implementation from everything else in // this file since this is using core wasm types instead of component // types, so a small part of the core wasm expansion process is // inlined here to handle the `TypeUse` from core wasm.
fn expand_sig<'a>(
item: &mut core::ItemSig<'a>,
to_prepend: &mut Vec<ModuleTypeDecl<'a>>,
func_type_to_idx: &mut HashMap<FuncKey<'a>, Index<'a>>,
) { match &mut item.kind {
core::ItemKind::Func(t) | core::ItemKind::Tag(core::TagType::Exception(t)) => { // If the index is already filled in then this is skipped. if t.index.is_some() { return;
}
// Otherwise the inline type information is used to // generate a type into this module if necessary. If the // function type already exists we reuse the same key, // otherwise a fresh type definition is created and we use // that one instead. let ty = t.inline.take().unwrap_or_default(); let key = ty.key(); iflet Some(idx) = func_type_to_idx.get(&key) {
t.index = Some(*idx); return;
} let id = gensym::gen(item.span);
to_prepend.push(ModuleTypeDecl::Type(core::Type {
span: item.span,
id: Some(id),
name: None, // Currently, there is no way in the WebAssembly text // format to mark a function `shared` inline; a // `shared` function must use an explicit type index, // e.g., `(func (type $ft))`.
def: key.to_def(item.span, /* shared = */ false),
})); let idx = Index::Id(id);
t.index = Some(idx);
}
core::ItemKind::Global(_)
| core::ItemKind::Table(_)
| core::ItemKind::Memory(_) => {}
}
}
}
fn expand_component_val_ty(&mutself, ty: &mut ComponentValType<'a>) { let inline = match ty {
ComponentValType::Inline(ComponentDefinedType::Primitive(_))
| ComponentValType::Ref(_) => return,
ComponentValType::Inline(inline) => { self.expand_defined_ty(inline);
mem::take(inline)
}
}; // 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. iflet Some(idx) = inline.key().lookup(self) {
*ty = ComponentValType::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);
let idx = Index::Id(id);
*ty = ComponentValType::Ref(idx);
}
fn expand_core_type_use<T>(
&mutself,
item: &mut CoreTypeUse<'a, T>,
) -> CoreItemRef<'a, kw::r#type> where
T: TypeReference<'a>,
{ let span = Span::from_offset(0); // FIXME(#613): don't manufacture letmut inline = match mem::take(item) { // If this type-use was already a reference to an existing type // then we put it back the way it was and return the corresponding // index.
CoreTypeUse::Ref(idx) => {
*item = CoreTypeUse::Ref(idx.clone()); return idx;
}
// ... otherwise with an inline type definition we go into // processing below.
CoreTypeUse::Inline(inline) => inline,
};
inline.expand(self);
// 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. iflet Some(idx) = inline.key().lookup(self) { let ret = CoreItemRef {
idx,
kind: kw::r#type(span),
export_name: None,
};
*item = CoreTypeUse::Ref(ret.clone()); return ret;
}
// And if this type isn't already defined we append it to the index // space with a fresh and unique name. let id = gensym::gen(span);
let idx = Index::Id(id); let ret = CoreItemRef {
idx,
kind: kw::r#type(span),
export_name: None,
};
*item = CoreTypeUse::Ref(ret.clone());
ret
}
fn expand_component_type_use<T>(
&mutself,
item: &mut ComponentTypeUse<'a, T>,
) -> ItemRef<'a, kw::r#type> where
T: TypeReference<'a>,
{ let span = Span::from_offset(0); // FIXME(#613): don't manufacture letmut inline = match mem::take(item) { // If this type-use was already a reference to an existing type // then we put it back the way it was and return the corresponding // index.
ComponentTypeUse::Ref(idx) => {
*item = ComponentTypeUse::Ref(idx.clone()); return idx;
}
// ... otherwise with an inline type definition we go into // processing below.
ComponentTypeUse::Inline(inline) => inline,
};
inline.expand(self);
// 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. iflet Some(idx) = inline.key().lookup(self) { let ret = ItemRef {
idx,
kind: kw::r#type(span),
export_names: Vec::new(),
};
*item = ComponentTypeUse::Ref(ret.clone()); return ret;
}
// And if this type isn't already defined we append it to the index // space with a fresh and unique name. let id = gensym::gen(span);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.