use crate::{name_map, Naming, Printer, State};
use anyhow::{bail, Result};
use wasmparser::*;
impl Printer<'_, '_> {
pub(crate) fn register_component_names(
&mut self,
state: &mut State,
names: ComponentNameSectionReader<'_>,
) -> Result<()> {
for section in names {
match section? {
ComponentName::Component { name, .. } => {
let name = Naming::new(name, 0, "component", None);
state.name = Some(name);
}
ComponentName::CoreFuncs(n) => {
name_map(&mut state.core.func_names, n, "core-func")?
}
ComponentName::CoreTypes(n) => {
name_map(&mut state.core.type_names, n, "core-type")?
}
ComponentName::CoreTables(n) => {
name_map(&mut state.core.table_names, n, "core-table")?
}
ComponentName::CoreMemories(n) => {
name_map(&mut state.core.memory_names, n, "core-memory")?
}
ComponentName::CoreGlobals(n) => {
name_map(&mut state.core.global_names, n, "core-global")?
}
ComponentName::CoreModules(n) => {
name_map(&mut state.core.module_names, n, "core-module")?
}
ComponentName::CoreInstances(n) => {
name_map(&mut state.core.instance_names, n, "core-instance")?
}
ComponentName::Types(n) => name_map(&mut state.component.type_names, n, "type")?,
ComponentName::Instances(n) => {
name_map(&mut state.component.instance_names, n, "instance")?
}
ComponentName::Components(n) => {
name_map(&mut state.component.component_names, n, "component")?
}
ComponentName::Funcs(n) => name_map(&mut state.component.func_names, n, "func")?,
ComponentName::Values(n) => name_map(&mut state.component.value_names, n, "value")?,
ComponentName::Unknown { .. } => (),
}
}
Ok(())
}
pub(crate) fn print_core_types(
&mut self,
states: &mut Vec<State>,
parser: CoreTypeSectionReader<'_>,
) -> Result<()> {
for ty in parser.into_iter_with_offsets() {
let (offset, ty) = ty?;
self.newline(offset)?;
self.print_core_type(states, ty)?;
}
Ok(())
}
pub(crate) fn print_core_type(&mut self, states: &mut Vec<State>, ty: CoreType) -> Result<()> {
match ty {
CoreType::Rec(rec) => {
self.print_rec(states.last_mut().unwrap(), None, rec, true)?;
}
CoreType::Module(decls) => {
self.start_group("core type ")?;
self.print_name(
&states.last().unwrap().core.type_names,
states.last().unwrap().core.types.len() as u32,
)?;
self.print_module_type(states, decls.into_vec())?;
self.end_group()?; states.last_mut().unwrap().core.types.push(None);
}
}
Ok(())
}
pub(crate) fn print_component_type_ref(&mut self, state: &State, idx: u32) -> Result<()> {
self.start_group("type ")?;
self.print_idx(&state.component.type_names, idx)?;
self.end_group()?;
Ok(())
}
pub(crate) fn print_primitive_val_type(&mut self, ty: &PrimitiveValType) -> Result<()> {
match ty {
PrimitiveValType::Bool => self.print_type_keyword("bool")?,
PrimitiveValType::S8 => self.print_type_keyword("s8")?,
PrimitiveValType::U8 => self.print_type_keyword("u8")?,
PrimitiveValType::S16 => self.print_type_keyword("s16")?,
PrimitiveValType::U16 => self.print_type_keyword("u16")?,
PrimitiveValType::S32 => self.print_type_keyword("s32")?,
PrimitiveValType::U32 => self.print_type_keyword("u32")?,
PrimitiveValType::S64 => self.print_type_keyword("s64")?,
PrimitiveValType::U64 => self.print_type_keyword("u64")?,
PrimitiveValType::F32 => self.print_type_keyword("f32")?,
PrimitiveValType::F64 => self.print_type_keyword("f64")?,
PrimitiveValType::Char => self.print_type_keyword("char")?,
PrimitiveValType::String => self.print_type_keyword("string")?,
}
Ok(())
}
pub(crate) fn print_record_type(
&mut self,
state: &State,
fields: &[(&str, ComponentValType)],
) -> Result<()> {
self.start_group("record")?;
for (name, ty) in fields.iter() {
self.result.write_str(" ")?;
self.start_group("field ")?;
self.print_str(name)?;
self.result.write_str(" ")?;
self.print_component_val_type(state, ty)?;
self.end_group()?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_variant_type(
&mut self,
state: &State,
cases: &[VariantCase],
) -> Result<()> {
self.start_group("variant")?;
for case in cases {
self.result.write_str(" ")?;
self.start_group("case ")?;
self.print_str(case.name)?;
if let Some(ty) = case.ty {
self.result.write_str(" ")?;
self.print_component_val_type(state, &ty)?;
}
if let Some(refines) = case.refines {
self.result.write_str(" ")?;
self.start_group("refines ")?;
write!(&mut self.result, "{}", refines)?;
self.end_group()?;
}
self.end_group()?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_list_type(
&mut self,
state: &State,
element_ty: &ComponentValType,
) -> Result<()> {
self.start_group("list ")?;
self.print_component_val_type(state, element_ty)?;
self.end_group()?;
Ok(())
}
pub(crate) fn print_tuple_type(
&mut self,
state: &State,
tys: &[ComponentValType],
) -> Result<()> {
self.start_group("tuple")?;
for ty in tys {
self.result.write_str(" ")?;
self.print_component_val_type(state, ty)?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_flag_or_enum_type(&mut self, ty: &str, names: &[&str]) -> Result<()> {
self.start_group(ty)?;
for name in names {
self.result.write_str(" ")?;
self.print_str(name)?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_option_type(
&mut self,
state: &State,
inner: &ComponentValType,
) -> Result<()> {
self.start_group("option ")?;
self.print_component_val_type(state, inner)?;
self.end_group()?;
Ok(())
}
pub(crate) fn print_result_type(
&mut self,
state: &State,
ok: Option<ComponentValType>,
err: Option<ComponentValType>,
) -> Result<()> {
self.start_group("result")?;
if let Some(ok) = ok {
self.result.write_str(" ")?;
self.print_component_val_type(state, &ok)?;
}
if let Some(err) = err {
self.result.write_str(" ")?;
self.start_group("error ")?;
self.print_component_val_type(state, &err)?;
self.end_group()?;
}
self.end_group()?;
Ok(())
}
fn print_future_type(&mut self, state: &State, ty: Option<ComponentValType>) -> Result<()> {
self.start_group("future")?;
if let Some(ty) = ty {
self.result.write_str(" ")?;
self.print_component_val_type(state, &ty)?;
}
self.end_group()?;
Ok(())
}
fn print_stream_type(&mut self, state: &State, ty: Option<ComponentValType>) -> Result<()> {
self.start_group("stream")?;
if let Some(ty) = ty {
self.result.write_str(" ")?;
self.print_component_val_type(state, &ty)?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_defined_type(
&mut self,
state: &State,
ty: &ComponentDefinedType,
) -> Result<()> {
match ty {
ComponentDefinedType::Primitive(ty) => self.print_primitive_val_type(ty)?,
ComponentDefinedType::Record(fields) => self.print_record_type(state, fields)?,
ComponentDefinedType::Variant(cases) => self.print_variant_type(state, cases)?,
ComponentDefinedType::List(ty) => self.print_list_type(state, ty)?,
ComponentDefinedType::Tuple(tys) => self.print_tuple_type(state, tys)?,
ComponentDefinedType::Flags(names) => self.print_flag_or_enum_type("flags", names)?,
ComponentDefinedType::Enum(cases) => self.print_flag_or_enum_type("enum", cases)?,
ComponentDefinedType::Option(ty) => self.print_option_type(state, ty)?,
ComponentDefinedType::Result { ok, err } => self.print_result_type(state, *ok, *err)?,
ComponentDefinedType::Own(idx) => {
self.start_group("own ")?;
self.print_idx(&state.component.type_names, *idx)?;
self.end_group()?;
}
ComponentDefinedType::Borrow(idx) => {
self.start_group("borrow ")?;
self.print_idx(&state.component.type_names, *idx)?;
self.end_group()?;
}
ComponentDefinedType::Future(ty) => self.print_future_type(state, *ty)?,
ComponentDefinedType::Stream(ty) => self.print_stream_type(state, *ty)?,
ComponentDefinedType::ErrorContext => self.print_type_keyword("error-context")?,
}
Ok(())
}
pub(crate) fn print_component_val_type(
&mut self,
state: &State,
ty: &ComponentValType,
) -> Result<()> {
match ty {
ComponentValType::Primitive(ty) => self.print_primitive_val_type(ty),
ComponentValType::Type(idx) => self.print_idx(&state.component.type_names, *idx),
}
}
pub(crate) fn print_module_type(
&mut self,
states: &mut Vec<State>,
decls: Vec<ModuleTypeDeclaration>,
) -> Result<()> {
states.push(State::new(Encoding::Module));
self.newline_unknown_pos()?;
self.start_group("module")?;
for decl in decls {
self.newline_unknown_pos()?;
match decl {
ModuleTypeDeclaration::Type(rec) => {
self.print_rec(states.last_mut().unwrap(), None, rec, false)?
}
ModuleTypeDeclaration::OuterAlias { kind, count, index } => {
self.print_outer_alias(states, kind, count, index)?;
}
ModuleTypeDeclaration::Export { name, ty } => {
self.start_group("export ")?;
self.print_str(name)?;
self.result.write_str(" ")?;
self.print_import_ty(states.last_mut().unwrap(), &ty, false)?;
self.end_group()?;
}
ModuleTypeDeclaration::Import(import) => {
self.print_import(states.last_mut().unwrap(), &import, false)?;
}
}
}
self.end_group()?;
states.pop();
Ok(())
}
pub(crate) fn print_component_type<'a>(
&mut self,
states: &mut Vec<State>,
decls: Vec<ComponentTypeDeclaration<'a>>,
) -> Result<()> {
states.push(State::new(Encoding::Component));
self.newline_unknown_pos()?;
self.start_group("component")?;
for decl in decls {
self.newline_unknown_pos()?;
match decl {
ComponentTypeDeclaration::CoreType(ty) => self.print_core_type(states, ty)?,
ComponentTypeDeclaration::Type(ty) => self.print_component_type_def(states, ty)?,
ComponentTypeDeclaration::Alias(alias) => {
self.print_component_alias(states, alias)?;
}
ComponentTypeDeclaration::Export { name, ty } => {
self.start_group("export ")?;
self.print_component_kind_name(states.last_mut().unwrap(), ty.kind())?;
self.result.write_str(" ")?;
self.print_str(name.0)?;
self.result.write_str(" ")?;
self.print_component_import_ty(states.last_mut().unwrap(), &ty, false)?;
self.end_group()?;
}
ComponentTypeDeclaration::Import(import) => {
self.print_component_import(states.last_mut().unwrap(), &import, true)?
}
}
}
self.end_group()?;
states.pop().unwrap();
Ok(())
}
pub(crate) fn print_instance_type<'a>(
&mut self,
states: &mut Vec<State>,
decls: Vec<InstanceTypeDeclaration<'a>>,
) -> Result<()> {
states.push(State::new(Encoding::Component));
self.newline_unknown_pos()?;
self.start_group("instance")?;
for decl in decls {
self.newline_unknown_pos()?;
match decl {
InstanceTypeDeclaration::CoreType(ty) => self.print_core_type(states, ty)?,
InstanceTypeDeclaration::Type(ty) => self.print_component_type_def(states, ty)?,
InstanceTypeDeclaration::Alias(alias) => {
self.print_component_alias(states, alias)?;
}
InstanceTypeDeclaration::Export { name, ty } => {
self.start_group("export ")?;
self.print_component_kind_name(states.last_mut().unwrap(), ty.kind())?;
self.result.write_str(" ")?;
self.print_str(name.0)?;
self.result.write_str(" ")?;
self.print_component_import_ty(states.last_mut().unwrap(), &ty, false)?;
self.end_group()?;
}
}
}
self.end_group()?;
states.pop().unwrap();
Ok(())
}
pub(crate) fn outer_state(states: &[State], count: u32) -> Result<&State> {
let count = count as usize;
if count >= states.len() {
bail!("invalid outer alias count of {}", count);
}
Ok(&states[states.len() - count - 1])
}
pub(crate) fn print_outer_alias(
&mut self,
states: &mut [State],
kind: OuterAliasKind,
count: u32,
index: u32,
) -> Result<()> {
let state = states.last().unwrap();
let outer = Self::outer_state(states, count)?;
self.start_group("alias outer ")?;
if let Some(name) = outer.name.as_ref() {
name.write(self)?;
} else {
write!(self.result, "{count}")?;
}
self.result.write_str(" ")?;
match kind {
OuterAliasKind::Type => {
self.print_idx(&outer.core.type_names, index)?;
self.result.write_str(" ")?;
self.start_group("type ")?;
self.print_name(&state.core.type_names, state.core.types.len() as u32)?;
}
}
self.end_group()?; self.end_group()?; let state = states.last_mut().unwrap();
match kind {
OuterAliasKind::Type => state.core.types.push(None),
}
Ok(())
}
pub(crate) fn print_component_func_type(
&mut self,
state: &State,
ty: &ComponentFuncType,
) -> Result<()> {
self.start_group("func")?;
for (name, ty) in ty.params.iter() {
self.result.write_str(" ")?;
self.start_group("param ")?;
self.print_str(name)?;
self.result.write_str(" ")?;
self.print_component_val_type(state, ty)?;
self.end_group()?;
}
if let Some(ty) = &ty.result {
self.result.write_str(" ")?;
self.start_group("result ")?;
self.print_component_val_type(state, ty)?;
self.end_group()?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_component_type_def<'a>(
&mut self,
states: &mut Vec<State>,
ty: ComponentType<'a>,
) -> Result<()> {
self.start_group("type ")?;
{
let state = states.last_mut().unwrap();
self.print_name(&state.component.type_names, state.component.types)?;
}
match ty {
ComponentType::Defined(ty) => {
self.result.write_str(" ")?;
self.print_defined_type(states.last_mut().unwrap(), &ty)?;
}
ComponentType::Func(ty) => {
self.result.write_str(" ")?;
self.print_component_func_type(states.last_mut().unwrap(), &ty)?;
}
ComponentType::Component(decls) => {
self.print_component_type(states, decls.into_vec())?;
}
ComponentType::Instance(decls) => {
self.print_instance_type(states, decls.into_vec())?;
}
ComponentType::Resource { rep, dtor } => {
self.result.write_str(" ")?;
self.start_group("resource ")?;
self.start_group("rep ")?;
self.print_valtype(states.last().unwrap(), rep)?;
self.end_group()?;
if let Some(dtor) = dtor {
self.result.write_str(" ")?;
self.start_group("dtor ")?;
self.start_group("func ")?;
self.print_idx(&states.last().unwrap().core.func_names, dtor)?;
self.end_group()?;
self.end_group()?;
}
self.end_group()?;
}
}
self.end_group()?;
states.last_mut().unwrap().component.types += 1;
Ok(())
}
pub(crate) fn print_component_types<'a>(
&mut self,
states: &mut Vec<State>,
parser: ComponentTypeSectionReader<'a>,
) -> Result<()> {
for ty in parser.into_iter_with_offsets() {
let (offset, ty) = ty?;
self.newline(offset)?;
self.print_component_type_def(states, ty)?;
}
Ok(())
}
pub(crate) fn print_component_imports(
&mut self,
state: &mut State,
parser: ComponentImportSectionReader,
) -> Result<()> {
for import in parser.into_iter_with_offsets() {
let (offset, import) = import?;
self.newline(offset)?;
self.print_component_import(state, &import, true)?;
}
Ok(())
}
pub(crate) fn print_component_import(
&mut self,
state: &mut State,
import: &ComponentImport,
index: bool,
) -> Result<()> {
self.start_group("import ")?;
self.print_str(import.name.0)?;
self.result.write_str(" ")?;
self.print_component_import_ty(state, &import.ty, index)?;
self.end_group()?;
Ok(())
}
pub(crate) fn print_component_import_ty(
&mut self,
state: &mut State,
ty: &ComponentTypeRef,
index: bool,
) -> Result<()> {
match ty {
ComponentTypeRef::Module(idx) => {
self.start_group("core module ")?;
if index {
self.print_name(&state.core.module_names, state.core.modules as u32)?;
self.result.write_str(" ")?;
state.core.modules += 1;
}
self.print_core_type_ref(state, *idx)?;
self.end_group()?;
}
ComponentTypeRef::Func(idx) => {
self.start_group("func ")?;
if index {
self.print_name(&state.component.func_names, state.component.funcs)?;
self.result.write_str(" ")?;
state.component.funcs += 1;
}
self.print_component_type_ref(state, *idx)?;
self.end_group()?;
}
ComponentTypeRef::Value(ty) => {
self.start_group("value ")?;
if index {
self.print_name(&state.component.value_names, state.component.values)?;
self.result.write_str(" ")?;
state.component.values += 1;
}
match ty {
ComponentValType::Primitive(ty) => self.print_primitive_val_type(ty)?,
ComponentValType::Type(idx) => self.print_component_type_ref(state, *idx)?,
}
self.end_group()?;
}
ComponentTypeRef::Type(bounds) => {
self.start_group("type ")?;
if index {
self.print_name(&state.component.type_names, state.component.types)?;
self.result.write_str(" ")?;
state.component.types += 1;
}
match bounds {
TypeBounds::Eq(idx) => {
self.start_group("eq ")?;
self.print_idx(&state.component.type_names, *idx)?;
self.end_group()?;
}
TypeBounds::SubResource => {
self.start_group("sub ")?;
self.print_type_keyword("resource")?;
self.end_group()?;
}
};
self.end_group()?;
}
ComponentTypeRef::Instance(idx) => {
self.start_group("instance ")?;
if index {
self.print_name(&state.component.instance_names, state.component.instances)?;
self.result.write_str(" ")?;
state.component.instances += 1;
}
self.print_component_type_ref(state, *idx)?;
self.end_group()?;
}
ComponentTypeRef::Component(idx) => {
self.start_group("component ")?;
if index {
self.print_name(&state.component.component_names, state.component.components)?;
self.result.write_str(" ")?;
state.component.components += 1;
}
self.print_component_type_ref(state, *idx)?;
self.end_group()?;
}
}
Ok(())
}
pub(crate) fn print_component_exports(
&mut self,
state: &mut State,
parser: ComponentExportSectionReader,
) -> Result<()> {
for export in parser.into_iter_with_offsets() {
let (offset, export) = export?;
self.newline(offset)?;
self.print_component_export(state, &export, true)?;
}
Ok(())
}
pub(crate) fn print_component_export(
&mut self,
state: &mut State,
export: &ComponentExport,
named: bool,
) -> Result<()> {
self.start_group("export ")?;
if named {
self.print_component_kind_name(state, export.kind)?;
self.result.write_str(" ")?;
}
self.print_str(export.name.0)?;
self.result.write_str(" ")?;
self.print_component_external_kind(state, export.kind, export.index)?;
if let Some(ty) = &export.ty {
self.result.write_str(" ")?;
self.print_component_import_ty(state, &ty, false)?;
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_component_kind_name(
&mut self,
state: &mut State,
kind: ComponentExternalKind,
) -> Result<()> {
match kind {
ComponentExternalKind::Func => {
self.print_name(&state.component.func_names, state.component.funcs)?;
state.component.funcs += 1;
}
ComponentExternalKind::Module => {
self.print_name(&state.core.module_names, state.core.modules)?;
state.core.modules += 1;
}
ComponentExternalKind::Value => {
self.print_name(&state.component.value_names, state.component.values)?;
state.component.values += 1;
}
ComponentExternalKind::Type => {
self.print_name(&state.component.type_names, state.component.types)?;
state.component.types += 1;
}
ComponentExternalKind::Instance => {
self.print_name(&state.component.instance_names, state.component.instances)?;
state.component.instances += 1;
}
ComponentExternalKind::Component => {
self.print_name(&state.component.component_names, state.component.components)?;
state.component.components += 1;
}
}
Ok(())
}
pub(crate) fn start_component_external_kind_group(
&mut self,
kind: ComponentExternalKind,
) -> Result<()> {
match kind {
ComponentExternalKind::Module => {
self.start_group("core module ")?;
}
ComponentExternalKind::Component => {
self.start_group("component ")?;
}
ComponentExternalKind::Instance => {
self.start_group("instance ")?;
}
ComponentExternalKind::Func => {
self.start_group("func ")?;
}
ComponentExternalKind::Value => {
self.start_group("value ")?;
}
ComponentExternalKind::Type => {
self.start_group("type ")?;
}
}
Ok(())
}
pub(crate) fn print_component_external_kind(
&mut self,
state: &State,
kind: ComponentExternalKind,
index: u32,
) -> Result<()> {
self.start_component_external_kind_group(kind)?;
match kind {
ComponentExternalKind::Module => {
self.print_idx(&state.core.module_names, index)?;
}
ComponentExternalKind::Component => {
self.print_idx(&state.component.component_names, index)?;
}
ComponentExternalKind::Instance => {
self.print_idx(&state.component.instance_names, index)?;
}
ComponentExternalKind::Func => {
self.print_idx(&state.component.func_names, index)?;
}
ComponentExternalKind::Value => {
self.print_idx(&state.component.value_names, index)?;
}
ComponentExternalKind::Type => {
self.print_idx(&state.component.type_names, index)?;
}
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_canonical_options(
&mut self,
state: &State,
options: &[CanonicalOption],
) -> Result<()> {
for option in options {
self.result.write_str(" ")?;
match option {
CanonicalOption::UTF8 => self.result.write_str("string-encoding=utf8")?,
CanonicalOption::UTF16 => self.result.write_str("string-encoding=utf16")?,
CanonicalOption::CompactUTF16 => {
self.result.write_str("string-encoding=latin1+utf16")?
}
CanonicalOption::Memory(idx) => {
self.start_group("memory ")?;
self.print_idx(&state.core.memory_names, *idx)?;
self.end_group()?;
}
CanonicalOption::Realloc(idx) => {
self.start_group("realloc ")?;
self.print_idx(&state.core.func_names, *idx)?;
self.end_group()?;
}
CanonicalOption::PostReturn(idx) => {
self.start_group("post-return ")?;
self.print_idx(&state.core.func_names, *idx)?;
self.end_group()?;
}
CanonicalOption::Async => self.result.write_str("async")?,
CanonicalOption::Callback(idx) => {
self.start_group("callback ")?;
self.print_idx(&state.core.func_names, *idx)?;
self.end_group()?;
}
}
}
Ok(())
}
fn print_intrinsic(
&mut self,
state: &mut State,
group: &str,
body: &dyn Fn(&mut Self, &mut State) -> Result<()>,
) -> Result<()> {
self.start_group("core func ")?;
self.print_name(&state.core.func_names, state.core.funcs)?;
self.result.write_str(" ")?;
self.start_group(group)?;
body(self, state)?;
self.end_group()?;
self.end_group()?;
debug_assert_eq!(state.core.func_to_type.len(), state.core.funcs as usize);
state.core.funcs += 1;
state.core.func_to_type.push(None);
Ok(())
}
pub(crate) fn print_canonical_functions(
&mut self,
state: &mut State,
parser: ComponentCanonicalSectionReader,
) -> Result<()> {
for func in parser.into_iter_with_offsets() {
let (offset, func) = func?;
self.newline(offset)?;
match func {
CanonicalFunction::Lift {
core_func_index,
type_index,
options,
} => {
self.start_group("func ")?;
self.print_name(&state.component.func_names, state.component.funcs)?;
self.result.write_str(" ")?;
self.start_group("type ")?;
self.print_idx(&state.component.type_names, type_index)?;
self.end_group()?;
self.result.write_str(" ")?;
self.start_group("canon lift ")?;
self.start_group("core func ")?;
self.print_idx(&state.core.func_names, core_func_index)?;
self.end_group()?;
self.print_canonical_options(state, &options)?;
self.end_group()?;
self.end_group()?;
state.component.funcs += 1;
}
CanonicalFunction::Lower {
func_index,
options,
} => {
self.print_intrinsic(state, "canon lower ", &|me, state| {
me.start_group("func ")?;
me.print_idx(&state.component.func_names, func_index)?;
me.end_group()?;
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::ResourceNew { resource } => {
self.print_intrinsic(state, "canon resource.new ", &|me, state| {
me.print_idx(&state.component.type_names, resource)
})?;
}
CanonicalFunction::ResourceDrop { resource } => {
self.print_intrinsic(state, "canon resource.drop ", &|me, state| {
me.print_idx(&state.component.type_names, resource)
})?;
}
CanonicalFunction::ResourceRep { resource } => {
self.print_intrinsic(state, "canon resource.rep ", &|me, state| {
me.print_idx(&state.component.type_names, resource)
})?;
}
CanonicalFunction::ThreadSpawn {
func_ty_index: func_index,
} => {
self.start_group("core func ")?;
self.print_name(&state.core.func_names, state.core.funcs)?;
self.result.write_str(" ")?;
self.start_group("canon thread.spawn ")?;
self.print_idx(&state.core.type_names, func_index)?;
self.end_group()?;
self.end_group()?;
state.core.funcs += 1;
}
CanonicalFunction::ThreadAvailableParallelism => {
self.start_group("core func ")?;
self.print_name(&state.core.func_names, state.core.funcs)?;
self.result.write_str(" ")?;
self.start_group("canon thread.available_parallelism")?;
self.end_group()?;
self.end_group()?;
state.core.funcs += 1;
}
CanonicalFunction::TaskBackpressure => {
self.print_intrinsic(state, "canon task.backpressure", &|_, _| Ok(()))?;
}
CanonicalFunction::TaskReturn { result } => {
self.print_intrinsic(state, "canon task.return", &|me, state| {
if let Some(ty) = result {
me.result.write_str(" ")?;
me.start_group("result ")?;
me.print_component_val_type(state, &ty)?;
me.end_group()?;
}
Ok(())
})?;
}
CanonicalFunction::TaskWait { async_, memory } => {
self.print_intrinsic(state, "canon task.wait ", &|me, state| {
if async_ {
me.result.write_str("async ")?;
}
me.start_group("memory ")?;
me.print_idx(&state.core.memory_names, memory)?;
me.end_group()
})?;
}
CanonicalFunction::TaskPoll { async_, memory } => {
self.print_intrinsic(state, "canon task.poll ", &|me, state| {
if async_ {
me.result.write_str("async ")?;
}
me.start_group("memory ")?;
me.print_idx(&state.core.memory_names, memory)?;
me.end_group()
})?;
}
CanonicalFunction::TaskYield { async_ } => {
self.print_intrinsic(state, "canon task.yield", &|me, _| {
if async_ {
me.result.write_str(" async")?;
}
Ok(())
})?;
}
CanonicalFunction::SubtaskDrop => {
self.print_intrinsic(state, "canon subtask.drop", &|_, _| Ok(()))?;
}
CanonicalFunction::StreamNew { ty } => {
self.print_intrinsic(state, "canon stream.new ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::StreamRead { ty, options } => {
self.print_intrinsic(state, "canon stream.read ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::StreamWrite { ty, options } => {
self.print_intrinsic(state, "canon stream.write ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::StreamCancelRead { ty, async_ } => {
self.print_intrinsic(state, "canon stream.cancel-read ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
if async_ {
me.result.write_str(" async")?;
}
Ok(())
})?;
}
CanonicalFunction::StreamCancelWrite { ty, async_ } => {
self.print_intrinsic(state, "canon stream.cancel-write ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
if async_ {
me.result.write_str(" async")?;
}
Ok(())
})?;
}
CanonicalFunction::StreamCloseReadable { ty } => {
self.print_intrinsic(state, "canon stream.close-readable ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::StreamCloseWritable { ty } => {
self.print_intrinsic(state, "canon stream.close-writable ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::FutureNew { ty } => {
self.print_intrinsic(state, "canon future.new ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::FutureRead { ty, options } => {
self.print_intrinsic(state, "canon future.read ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::FutureWrite { ty, options } => {
self.print_intrinsic(state, "canon future.write ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::FutureCancelRead { ty, async_ } => {
self.print_intrinsic(state, "canon future.cancel-read ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
if async_ {
me.result.write_str(" async")?;
}
Ok(())
})?;
}
CanonicalFunction::FutureCancelWrite { ty, async_ } => {
self.print_intrinsic(state, "canon future.cancel-write ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
if async_ {
me.result.write_str(" async")?;
}
Ok(())
})?;
}
CanonicalFunction::FutureCloseReadable { ty } => {
self.print_intrinsic(state, "canon future.close-readable ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::FutureCloseWritable { ty } => {
self.print_intrinsic(state, "canon future.close-writable ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::ErrorContextNew { options } => {
self.print_intrinsic(state, "canon error-context.new", &|me, state| {
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::ErrorContextDebugMessage { options } => {
self.print_intrinsic(
state,
"canon error-context.debug-message",
&|me, state| me.print_canonical_options(state, &options),
)?;
}
CanonicalFunction::ErrorContextDrop => {
self.print_intrinsic(state, "canon error-context.drop", &|_, _| Ok(()))?;
}
}
}
Ok(())
}
pub(crate) fn print_instances(
&mut self,
state: &mut State,
parser: InstanceSectionReader,
) -> Result<()> {
for instance in parser.into_iter_with_offsets() {
let (offset, instance) = instance?;
self.newline(offset)?;
self.start_group("core instance ")?;
self.print_name(&state.core.instance_names, state.core.instances)?;
match instance {
Instance::Instantiate { module_index, args } => {
self.result.write_str(" ")?;
self.start_group("instantiate ")?;
self.print_idx(&state.core.module_names, module_index)?;
for arg in args.iter() {
self.newline(offset)?;
self.print_instantiation_arg(state, arg)?;
}
self.end_group()?;
state.core.instances += 1;
}
Instance::FromExports(exports) => {
for export in exports.iter() {
self.newline(offset)?;
self.print_export(state, export)?;
}
state.core.instances += 1;
}
}
self.end_group()?;
}
Ok(())
}
pub(crate) fn print_component_instances(
&mut self,
state: &mut State,
parser: ComponentInstanceSectionReader,
) -> Result<()> {
for instance in parser.into_iter_with_offsets() {
let (offset, instance) = instance?;
self.newline(offset)?;
self.start_group("instance ")?;
self.print_name(&state.component.instance_names, state.component.instances)?;
state.component.instances += 1;
match instance {
ComponentInstance::Instantiate {
component_index,
args,
} => {
self.result.write_str(" ")?;
self.start_group("instantiate ")?;
self.print_idx(&state.component.component_names, component_index)?;
for arg in args.iter() {
self.newline(offset)?;
self.print_component_instantiation_arg(state, arg)?;
}
self.end_group()?;
}
ComponentInstance::FromExports(exports) => {
for export in exports.iter() {
self.newline(offset)?;
self.print_component_export(state, export, false)?;
}
}
}
self.end_group()?;
}
Ok(())
}
pub(crate) fn print_instantiation_arg(
&mut self,
state: &State,
arg: &InstantiationArg,
) -> Result<()> {
self.start_group("with ")?;
self.print_str(arg.name)?;
self.result.write_str(" ")?;
match arg.kind {
InstantiationArgKind::Instance => {
self.start_group("instance ")?;
self.print_idx(&state.core.instance_names, arg.index)?;
self.end_group()?;
}
}
self.end_group()?;
Ok(())
}
pub(crate) fn print_component_instantiation_arg(
&mut self,
state: &State,
arg: &ComponentInstantiationArg,
) -> Result<()> {
self.start_group("with ")?;
self.print_str(arg.name)?;
self.result.write_str(" ")?;
self.print_component_external_kind(state, arg.kind, arg.index)?;
self.end_group()?;
Ok(())
}
pub(crate) fn print_component_start(
&mut self,
state: &mut State,
pos: usize,
start: ComponentStartFunction,
) -> Result<()> {
self.newline(pos)?;
self.start_group("start ")?;
self.print_idx(&state.component.func_names, start.func_index)?;
for arg in start.arguments.iter() {
self.result.write_str(" ")?;
self.start_group("value ")?;
self.print_idx(&state.component.value_names, *arg)?;
self.end_group()?;
}
for _ in 0..start.results {
self.result.write_str(" ")?;
self.start_group("result ")?;
self.start_group("value ")?;
self.print_name(&state.component.value_names, state.component.values)?;
self.end_group()?;
self.end_group()?;
state.component.values += 1;
}
self.end_group()?; Ok(())
}
pub(crate) fn print_component_aliases(
&mut self,
states: &mut [State],
parser: ComponentAliasSectionReader,
) -> Result<()> {
for alias in parser.into_iter_with_offsets() {
let (offset, alias) = alias?;
self.newline(offset)?;
self.print_component_alias(states, alias)?;
}
Ok(())
}
pub(crate) fn print_component_alias(
&mut self,
states: &mut [State],
alias: ComponentAlias<'_>,
) -> Result<()> {
match alias {
ComponentAlias::InstanceExport {
kind,
instance_index,
name,
} => {
let state = states.last_mut().unwrap();
self.start_group("alias export ")?;
self.print_idx(&state.component.instance_names, instance_index)?;
self.result.write_str(" ")?;
self.print_str(name)?;
self.result.write_str(" ")?;
self.start_component_external_kind_group(kind)?;
self.print_component_kind_name(state, kind)?;
self.end_group()?;
self.end_group()?; }
ComponentAlias::CoreInstanceExport {
instance_index,
kind,
name,
} => {
let state = states.last_mut().unwrap();
self.start_group("alias core export ")?;
self.print_idx(&state.core.instance_names, instance_index)?;
self.result.write_str(" ")?;
self.print_str(name)?;
self.result.write_str(" ")?;
match kind {
ExternalKind::Func => {
self.start_group("core func ")?;
self.print_name(&state.core.func_names, state.core.funcs)?;
self.end_group()?;
debug_assert_eq!(state.core.func_to_type.len(), state.core.funcs as usize);
state.core.funcs += 1;
state.core.func_to_type.push(None)
}
ExternalKind::Table => {
self.start_group("core table ")?;
self.print_name(&state.core.table_names, state.core.tables)?;
self.end_group()?;
state.core.tables += 1;
}
ExternalKind::Memory => {
self.start_group("core memory ")?;
self.print_name(&state.core.memory_names, state.core.memories)?;
self.end_group()?;
state.core.memories += 1;
}
ExternalKind::Global => {
self.start_group("core global ")?;
self.print_name(&state.core.global_names, state.core.globals)?;
self.end_group()?;
state.core.globals += 1;
}
ExternalKind::Tag => {
self.start_group("core tag ")?;
self.print_name(&state.core.tag_names, state.core.tags as u32)?;
self.end_group()?;
debug_assert_eq!(state.core.tag_to_type.len(), state.core.tags as usize);
state.core.tags += 1;
state.core.tag_to_type.push(None)
}
}
self.end_group()?; }
ComponentAlias::Outer { kind, count, index } => {
let state = states.last().unwrap();
let outer = Self::outer_state(states, count)?;
self.start_group("alias outer ")?;
if let Some(name) = outer.name.as_ref() {
name.write(self)?;
} else {
write!(self.result, "{count}")?;
}
self.result.write_str(" ")?;
match kind {
ComponentOuterAliasKind::CoreModule => {
self.print_idx(&outer.core.module_names, index)?;
self.result.write_str(" ")?;
self.start_group("core module ")?;
self.print_name(&state.core.module_names, state.core.modules)?;
}
ComponentOuterAliasKind::CoreType => {
self.print_idx(&outer.core.type_names, index)?;
self.result.write_str(" ")?;
self.start_group("core type ")?;
self.print_name(&state.core.type_names, state.core.types.len() as u32)?;
}
ComponentOuterAliasKind::Type => {
self.print_idx(&outer.component.type_names, index)?;
self.result.write_str(" ")?;
self.start_group("type ")?;
self.print_name(&state.component.type_names, state.component.types)?;
}
ComponentOuterAliasKind::Component => {
self.print_idx(&outer.component.component_names, index)?;
self.result.write_str(" ")?;
self.start_group("component ")?;
self.print_name(
&state.component.component_names,
state.component.components,
)?;
}
}
self.end_group()?; self.end_group()?; let state = states.last_mut().unwrap();
match kind {
ComponentOuterAliasKind::CoreModule => state.core.modules += 1,
ComponentOuterAliasKind::CoreType => state.core.types.push(None),
ComponentOuterAliasKind::Type => state.component.types += 1,
ComponentOuterAliasKind::Component => state.component.components += 1,
}
}
}
Ok(())
}
}