#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ItemId {
Type(u32),
Func(u32),
Table(u32),
Memory(u32),
Global(u32),
Element(u32),
Data(u32),
Local {
func: u32,
local: u32,
},
Tag(u32),
}
pub trait Item {
fn print(
&self,
ctx: &crate::print::PrintContext,
p: &mut dyn crate::printer::Printer,
idx: u32,
);
}
use crate::ast::custom::CustomSection;
use crate::ast::data::Data;
use crate::ast::elements::Element;
use crate::ast::exports::Export;
use crate::ast::functions::{Func, FuncBody};
use crate::ast::globals::Global;
use crate::ast::imports::{Import, ImportType};
use crate::ast::memories::Memory;
use crate::ast::names::NameSection;
use crate::ast::tables::Table;
use crate::ast::tags::Tag;
use crate::ast::types::RecGroup;
use crate::Span;
#[derive(Debug, Clone, Eq)]
pub struct Module {
pub types: Vec<RecGroup>,
pub imports: Vec<Import>,
pub functions: Vec<Func>,
pub tables: Vec<Table>,
pub memories: Vec<Memory>,
pub tags: Vec<Tag>,
pub globals: Vec<Global>,
pub exports: Vec<Export>,
pub start: Option<u32>,
pub elements: Vec<Element>,
pub data_count: Option<u32>,
pub data: Vec<Data>,
pub bodies: Vec<FuncBody>,
pub names: NameSection,
pub custom_sections: Vec<CustomSection>,
}
impl PartialEq for Module {
fn eq(&self, other: &Self) -> bool {
self.types == other.types
&& self.imports == other.imports
&& self.functions == other.functions
&& self.tables == other.tables
&& self.memories == other.memories
&& self.tags == other.tags
&& self.globals == other.globals
&& self.exports == other.exports
&& self.start == other.start
&& self.elements == other.elements
&& self.data_count == other.data_count
&& self.data == other.data
&& self.bodies == other.bodies
&& self.names == other.names
&& self.custom_sections == other.custom_sections
}
}
impl Default for Module {
fn default() -> Self {
Self::new()
}
}
impl Module {
pub fn new() -> Self {
Module {
types: Vec::new(),
imports: Vec::new(),
functions: Vec::new(),
tables: Vec::new(),
memories: Vec::new(),
tags: Vec::new(),
globals: Vec::new(),
exports: Vec::new(),
start: None,
elements: Vec::new(),
data_count: None,
data: Vec::new(),
bodies: Vec::new(),
names: NameSection::default(),
custom_sections: Vec::new(),
}
}
}
impl Module {
pub fn find_closest_item(&self, id: &ItemId) -> Option<&dyn Item> {
match id {
ItemId::Type(i) => {
let mut remaining = *i as usize;
for group in &self.types {
if remaining < group.types.len() {
return Some(&group.types[remaining]);
}
remaining -= group.types.len();
}
None
}
ItemId::Func(i) => self.functions.get(*i as usize).map(|x| x as &dyn Item),
ItemId::Table(i) => self.tables.get(*i as usize).map(|x| x as &dyn Item),
ItemId::Memory(i) => self.memories.get(*i as usize).map(|x| x as &dyn Item),
ItemId::Global(i) => self.globals.get(*i as usize).map(|x| x as &dyn Item),
ItemId::Element(i) => self.elements.get(*i as usize).map(|x| x as &dyn Item),
ItemId::Data(i) => self.data.get(*i as usize).map(|x| x as &dyn Item),
ItemId::Local { func, .. } => {
self.functions.get(*func as usize).map(|x| x as &dyn Item)
}
ItemId::Tag(i) => self.tags.get(*i as usize).map(|x| x as &dyn Item),
}
}
pub fn definitions(&self) -> Vec<(ItemId, Span)> {
let mut result = Vec::new();
let mut type_idx = 0u32;
for group in &self.types {
for _ in &group.types {
result.push((ItemId::Type(type_idx), group.span));
type_idx += 1;
}
}
let mut func_idx = 0u32;
let mut table_idx = 0u32;
let mut memory_idx = 0u32;
let mut global_idx = 0u32;
let mut tag_idx = 0u32;
for import in &self.imports {
let id = match &import.ty {
ImportType::Func(_) => {
let id = ItemId::Func(func_idx);
func_idx += 1;
id
}
ImportType::Table(_) => {
let id = ItemId::Table(table_idx);
table_idx += 1;
id
}
ImportType::Memory(_) => {
let id = ItemId::Memory(memory_idx);
memory_idx += 1;
id
}
ImportType::Global(_) => {
let id = ItemId::Global(global_idx);
global_idx += 1;
id
}
ImportType::Tag(_) => {
let id = ItemId::Tag(tag_idx);
tag_idx += 1;
id
}
};
result.push((id, import.span));
}
for (i, func) in self.functions.iter().enumerate() {
result.push((ItemId::Func(func_idx + i as u32), func.span));
}
for (i, table) in self.tables.iter().enumerate() {
result.push((ItemId::Table(table_idx + i as u32), table.span));
}
for (i, memory) in self.memories.iter().enumerate() {
result.push((ItemId::Memory(memory_idx + i as u32), memory.span));
}
for (i, global) in self.globals.iter().enumerate() {
result.push((ItemId::Global(global_idx + i as u32), global.span));
}
for (i, tag) in self.tags.iter().enumerate() {
result.push((ItemId::Tag(tag_idx + i as u32), tag.span));
}
for (i, elem) in self.elements.iter().enumerate() {
result.push((ItemId::Element(i as u32), elem.span));
}
for (i, data) in self.data.iter().enumerate() {
result.push((ItemId::Data(i as u32), data.span));
}
result
}
}