// When a name refers to a definition in an outer scope, we'll need to // insert an outer alias before it. This collects the aliases to be // inserted during resolution.
aliases_to_insert: Vec<Alias<'a>>,
}
/// Context structure used to perform name resolution. #[derive(Default)] struct ComponentState<'a> {
id: Option<Id<'a>>,
// Namespaces within each component. Note that each namespace carries // with it information about the signature of the item in that namespace. // The signature is later used to synthesize the type of a component and // inject type annotations if necessary.
core_funcs: Namespace<'a>,
core_globals: Namespace<'a>,
core_tables: Namespace<'a>,
core_memories: Namespace<'a>,
core_types: Namespace<'a>,
core_tags: Namespace<'a>,
core_instances: Namespace<'a>,
core_modules: Namespace<'a>,
// Iterate through the fields of the component. We use an index // instead of an iterator because we'll be inserting aliases // as we go. letmut i = 0; while i < fields.len() { // Resolve names within the field.
resolve(self, &mut fields[i])?;
// Name resolution may have emitted some aliases. Insert them before // the current definition. let amt = self.aliases_to_insert.len();
fields.splice(i..i, self.aliases_to_insert.drain(..).map(T::from));
i += amt;
// Definitions can't refer to themselves or to definitions that appear // later in the format. Now that we're done resolving this field, // assign it an index for later definitions to refer to.
register(self.current(), &fields[i])?;
fn core_instance(&mutself, instance: &mut CoreInstance<'a>) -> Result<(), Error> { match &mut instance.kind {
CoreInstanceKind::Instantiate { module, args } => { self.component_item_ref(module)?; for arg in args { match &mut arg.kind {
CoreInstantiationArgKind::Instance(i) => { self.core_item_ref(i)?;
}
CoreInstantiationArgKind::BundleOfExports(..) => {
unreachable!("should be expanded already");
}
}
}
}
CoreInstanceKind::BundleOfExports(exports) => { for export in exports { self.core_item_ref(&mut export.item)?;
}
}
}
Ok(())
}
fn instance(&mutself, instance: &mut Instance<'a>) -> Result<(), Error> { match &mut instance.kind {
InstanceKind::Instantiate { component, args } => { self.component_item_ref(component)?; for arg in args { match &mut arg.kind {
InstantiationArgKind::Item(e) => { self.export(e)?;
}
InstantiationArgKind::BundleOfExports(..) => {
unreachable!("should be expanded already")
}
}
}
}
InstanceKind::BundleOfExports(exports) => { for export in exports { self.export(&mut export.kind)?;
}
}
InstanceKind::Import { .. } => {
unreachable!("should be expanded already")
}
}
Ok(())
}
fn item_sig(&mutself, item: &mut ItemSig<'a>) -> Result<(), Error> { match &mut item.kind { // Here we must be explicit otherwise the module type reference will // be assumed to be in the component type namespace
ItemSigKind::CoreModule(t) => self.core_type_use(t),
ItemSigKind::Func(t) => self.component_type_use(t),
ItemSigKind::Component(t) => self.component_type_use(t),
ItemSigKind::Instance(t) => self.component_type_use(t),
ItemSigKind::Value(t) => self.component_val_type(&mut t.0),
ItemSigKind::Type(b) => match b {
TypeBounds::Eq(i) => { self.resolve_ns(i, Ns::Type)?;
Ok(())
}
TypeBounds::SubResource => Ok(()),
},
}
}
fn export(&mutself, kind: &mut ComponentExportKind<'a>) -> Result<(), Error> { match kind { // Here we do *not* have to be explicit as the item ref is to a core module
ComponentExportKind::CoreModule(r) => self.component_item_ref(r),
ComponentExportKind::Func(r) => self.component_item_ref(r),
ComponentExportKind::Value(r) => self.component_item_ref(r),
ComponentExportKind::Type(r) => self.component_item_ref(r),
ComponentExportKind::Component(r) => self.component_item_ref(r),
ComponentExportKind::Instance(r) => self.component_item_ref(r),
}
}
fn outer_alias<T: Into<Ns>>(
&mutself,
outer: &mut Index<'a>,
index: &mut Index<'a>,
kind: T,
span: Span,
) -> Result<(), Error> { // Short-circuit when both indices are already resolved as this // helps to write tests for invalid modules where wasmparser should // be the one returning the error. iflet Index::Num(..) = outer { iflet Index::Num(..) = index { return Ok(());
}
}
// Resolve `outer`, and compute the depth at which to look up // `index`. let depth = match outer {
Index::Id(id) => { letmut depth = 0; for resolver inself.stack.iter().rev() { if resolver.id == Some(*id) { break;
}
depth += 1;
} if depth as usize == self.stack.len() { return Err(Error::new(
span,
format!("outer component `{}` not found", id.name()),
));
}
depth
}
Index::Num(n, _span) => *n,
};
if depth as usize >= self.stack.len() { return Err(Error::new(
span,
format!("outer count of `{}` is too large", depth),
));
}
*outer = Index::Num(depth, span);
// Resolve `index` within the computed scope depth. let computed = self.stack.len() - 1 - depth as usize; self.stack[computed].resolve(kind.into(), index)?;
fn core_type_use<T>(&mutself, ty: &mut CoreTypeUse<'a, T>) -> Result<(), Error> { let item = match ty {
CoreTypeUse::Ref(r) => r,
CoreTypeUse::Inline(_) => {
unreachable!("inline type-use should be expanded by now")
}
}; self.core_item_ref(item)
}
fn component_type_use<T>(&mutself, ty: &mut ComponentTypeUse<'a, T>) -> Result<(), Error> { let item = match ty {
ComponentTypeUse::Ref(r) => r,
ComponentTypeUse::Inline(_) => {
unreachable!("inline type-use should be expanded by now")
}
}; self.component_item_ref(item)
}
fn defined_type(&mutself, ty: &mut ComponentDefinedType<'a>) -> Result<(), Error> { match ty {
ComponentDefinedType::Primitive(_) => {}
ComponentDefinedType::Flags(_) => {}
ComponentDefinedType::Enum(_) => {}
ComponentDefinedType::Record(r) => { for field in r.fields.iter_mut() { self.component_val_type(&mut field.ty)?;
}
}
ComponentDefinedType::Variant(v) => { // Namespace for case identifier resolution letmut ns = Namespace::default(); for case in v.cases.iter_mut() { let index = ns.register(case.id, "variant case")?;
fn component_val_type(&mutself, ty: &mut ComponentValType<'a>) -> Result<(), Error> { match ty {
ComponentValType::Ref(idx) => { self.resolve_ns(idx, Ns::Type)?;
Ok(())
}
ComponentValType::Inline(ComponentDefinedType::Primitive(_)) => Ok(()),
ComponentValType::Inline(_) => unreachable!("should be expanded by now"),
}
}
fn core_ty(&mutself, field: &mut CoreType<'a>) -> Result<(), Error> { match &mut field.def {
CoreTypeDef::Def(ty) => { // See comments in `module_type` for why registration of ids happens // here for core types early. self.current().core_types.register(field.id, "core type")?; self.current().resolve_type_def(ty)?;
assert!(self.aliases_to_insert.is_empty());
}
CoreTypeDef::Module(t) => { self.stack.push(ComponentState::new(field.id)); self.module_type(t)?; self.stack.pop();
}
}
Ok(())
}
fn core_rec(&mutself, rec: &mut core::Rec<'a>) -> Result<(), Error> { // See comments in `module_type` for why registration of ids happens // here for core types early. for ty in rec.types.iter() { self.current().core_types.register(ty.id, "core type")?;
} for ty in rec.types.iter_mut() { self.current().resolve_type(ty)?;
}
assert!(self.aliases_to_insert.is_empty());
Ok(())
}
fn ty(&mutself, field: &mutType<'a>) -> Result<(), Error> { match &mut field.def {
TypeDef::Defined(t) => { self.defined_type(t)?;
}
TypeDef::Func(f) => { for param in f.params.iter_mut() { self.component_val_type(&mut param.ty)?;
}
fn core_item_ref<K>(&mutself, item: &mut CoreItemRef<'a, K>) -> Result<(), Error> where
K: CoreItem + Copy,
{ // Check for not being an instance export reference if item.export_name.is_none() { self.resolve_ns(&mut item.idx, item.kind.ns())?; return Ok(());
}
// This is a reference to a core instance export letmut index = item.idx; self.resolve_ns(&mut index, Ns::CoreInstance)?;
// Record an alias to reference the export let span = item.idx.span(); let alias = Alias {
span,
id: None,
name: None,
target: AliasTarget::CoreExport {
instance: index,
name: item.export_name.unwrap(),
kind: item.kind.ns().into(),
},
};
index = Index::Num(self.current().register_alias(&alias)?, span); self.aliases_to_insert.push(alias);
item.idx = index;
item.export_name = None;
Ok(())
}
fn component_item_ref<K>(&mutself, item: &>mut ItemRef<'a, K>) -> Result<(), Error> where
K: ComponentItem + Copy,
{ // Check for not being an instance export reference if item.export_names.is_empty() { self.resolve_ns(&mut item.idx, item.kind.ns())?; return Ok(());
}
// This is a reference to an instance export letmut index = item.idx; self.resolve_ns(&mut index, Ns::Instance)?;
let span = item.idx.span(); for (pos, export_name) in item.export_names.iter().enumerate() { // Record an alias to reference the export let alias = Alias {
span,
id: None,
name: None,
target: AliasTarget::Export {
instance: index,
name: export_name,
kind: if pos == item.export_names.len() - 1 {
item.kind.ns().into()
} else {
ComponentExportAliasKind::Instance
},
},
};
index = Index::Num(self.current().register_alias(&alias)?, span); self.aliases_to_insert.push(alias);
}
item.idx = index;
item.export_names = Vec::new();
Ok(())
}
fn resolve_ns(&mutself, idx: &mut Index<'a>, ns: Ns) -> Result<u32, Error> { // Perform resolution on a local clone walking up the stack of components // that we have. Note that a local clone is used since we don't want to use // the parent's resolved index if a parent matches, instead we want to use // the index of the alias that we will automatically insert. letmut idx_clone = *idx; for (depth, resolver) inself.stack.iter_mut().rev().enumerate() { let depth = depth as u32; let found = match resolver.resolve(ns, &mut idx_clone) {
Ok(idx) => idx, // Try the next parent
Err(_) => continue,
};
// If this is the current component then no extra alias is necessary, so // return success. if depth == 0 {
*idx = idx_clone; return Ok(found);
} let id = match idx {
Index::Id(id) => *id,
Index::Num(..) => unreachable!(),
};
// When resolution succeeds in a parent then an outer alias is // automatically inserted here in this component. let span = idx.span(); let alias = Alias {
span,
id: Some(id),
name: None,
target: AliasTarget::Outer {
outer: Index::Num(depth, span),
index: Index::Num(found, span),
kind: ns.into(),
},
}; let local_index = self.current().register_alias(&alias)?; self.aliases_to_insert.push(alias);
*idx = Index::Num(local_index, span); return Ok(local_index);
}
// If resolution in any parent failed then simply return the error from our // local namespace self.current().resolve(ns, idx)?;
unreachable!()
}
// For types since the GC proposal to core wasm they're allowed // to both refer to themselves and additionally a recursion // group can define a set of types that all refer to one // another. That means that the type names must be registered // first before the type is resolved so the type's own name is // in scope for itself. // // Note though that this means that aliases cannot be injected // automatically for references to outer types. We don't know // how many aliases are going to be created so we otherwise // don't know the type index to register. // // As a compromise for now core types don't support // auto-injection of aliases from outer scopes. They must be // explicitly aliased in. Also note that the error message isn't // great either. This may be something we want to improve in the // future with a better error message or a pass that goes over // everything first to inject aliases and then afterwards all // other names are registered.
ModuleTypeDecl::Type(t) => {
resolver.current().core_types.register(t.id, "type")?;
resolver.current().resolve_type(t)
}
ModuleTypeDecl::Rec(t) => { for t in t.types.iter_mut() {
resolver.current().core_types.register(t.id, "type")?;
} for t in t.types.iter_mut() {
resolver.current().resolve_type(t)?;
}
Ok(())
}
ModuleTypeDecl::Import(import) => resolve_item_sig(resolver, &mut import.item),
ModuleTypeDecl::Export(_, item) => resolve_item_sig(resolver, item),
},
|state, decl| { match decl {
ModuleTypeDecl::Alias(alias) => {
state.register_alias(alias)?;
} // These were registered above already
ModuleTypeDecl::Type(_) | ModuleTypeDecl::Rec(_) => {} // Only the type namespace is populated within the module type // namespace so these are ignored here.
ModuleTypeDecl::Import(_) | ModuleTypeDecl::Export(..) => {}
}
Ok(())
},
);
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.