1 use crate::ast::*;
2 use crate::Error;
3
4 mod expand;
5 mod names;
6 mod tyexpand;
7
resolve<'a>(module: &mut Module<'a>) -> Result<Names<'a>, Error>8 pub fn resolve<'a>(module: &mut Module<'a>) -> Result<Names<'a>, Error> {
9 let fields = match &mut module.kind {
10 ModuleKind::Text(fields) => fields,
11 _ => return Ok(Default::default()),
12 };
13
14 // First up, let's de-inline import/export annotations since this'll
15 // restructure the module and affect how we count indices in future passes
16 // since function definitions turn into imports.
17 //
18 // The first pass switches all inline imports to explicit `Import` items.
19 // This pass also counts all `Import` items per-type to start building up
20 // the index space so we know the corresponding index for each item.
21 //
22 // In a second pass we then remove all inline `export` annotations, again
23 // counting indices as we go along to ensure we always know the index for
24 // what we're exporting.
25 //
26 // The final step is then taking all of the injected `export` fields and
27 // actually pushing them onto our list of fields.
28 let mut expander = expand::Expander::default();
29 expander.process(fields, expand::Expander::deinline_import);
30 expander.process(fields, expand::Expander::deinline_export);
31
32 for i in 1..fields.len() {
33 let span = match &fields[i] {
34 ModuleField::Import(i) => i.span,
35 _ => continue,
36 };
37 let name = match &fields[i - 1] {
38 ModuleField::Memory(_) => "memory",
39 ModuleField::Func(_) => "function",
40 ModuleField::Table(_) => "table",
41 ModuleField::Global(_) => "global",
42 _ => continue,
43 };
44 return Err(Error::new(span, format!("import after {}", name)));
45 }
46
47 // For the second pass we resolve all inline type annotations. This will, in
48 // the order that we see them, append to the list of types. Note that types
49 // are indexed so we're careful to always insert new types just before the
50 // field that we're looking at.
51 //
52 // It's not strictly required that we `move_types_first` here but it gets
53 // our indexing to exactly match wabt's which our test suite is asserting.
54 let mut cur = 0;
55 let mut expander = tyexpand::Expander::default();
56 move_types_first(fields);
57 while cur < fields.len() {
58 expander.expand(&mut fields[cur]);
59 for new in expander.to_prepend.drain(..) {
60 fields.insert(cur, new);
61 cur += 1;
62 }
63 cur += 1;
64 }
65
66 // Perform name resolution over all `Index` items to resolve them all to
67 // indices instead of symbolic names.
68 //
69 // For this operation we do need to make sure that imports are sorted first
70 // because otherwise we'll be calculating indices in the wrong order.
71 move_imports_first(fields);
72 let mut resolver = names::Resolver::default();
73 for field in fields.iter_mut() {
74 resolver.register(field)?;
75 }
76 for field in fields.iter_mut() {
77 resolver.resolve(field)?;
78 }
79 Ok(Names { resolver })
80 }
81
move_imports_first(fields: &mut [ModuleField<'_>])82 fn move_imports_first(fields: &mut [ModuleField<'_>]) {
83 fields.sort_by_key(|f| match f {
84 ModuleField::Import(_) => false,
85 _ => true,
86 });
87 }
88
move_types_first(fields: &mut [ModuleField<'_>])89 fn move_types_first(fields: &mut [ModuleField<'_>]) {
90 fields.sort_by_key(|f| match f {
91 ModuleField::Type(_) => false,
92 _ => true,
93 });
94 }
95
96 /// Representation of the results of name resolution for a module.
97 ///
98 /// This structure is returned from the
99 /// [`Module::resolve`](crate::Module::resolve) function and can be used to
100 /// resolve your own name arguments if you have any.
101 #[derive(Default)]
102 pub struct Names<'a> {
103 resolver: names::Resolver<'a>,
104 }
105
106 impl<'a> Names<'a> {
107 /// Resolves `idx` within the function namespace.
108 ///
109 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
110 /// looked up in the function namespace and converted to a `Num`. If the
111 /// `Id` is not defined then an error will be returned.
resolve_func(&self, idx: &mut Index<'a>) -> Result<(), Error>112 pub fn resolve_func(&self, idx: &mut Index<'a>) -> Result<(), Error> {
113 self.resolver.resolve_idx(idx, names::Ns::Func)
114 }
115
116 /// Resolves `idx` within the memory namespace.
117 ///
118 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
119 /// looked up in the memory namespace and converted to a `Num`. If the
120 /// `Id` is not defined then an error will be returned.
resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error>121 pub fn resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error> {
122 self.resolver.resolve_idx(idx, names::Ns::Memory)
123 }
124
125 /// Resolves `idx` within the table namespace.
126 ///
127 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
128 /// looked up in the table namespace and converted to a `Num`. If the
129 /// `Id` is not defined then an error will be returned.
resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error>130 pub fn resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error> {
131 self.resolver.resolve_idx(idx, names::Ns::Table)
132 }
133
134 /// Resolves `idx` within the global namespace.
135 ///
136 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
137 /// looked up in the global namespace and converted to a `Num`. If the
138 /// `Id` is not defined then an error will be returned.
resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error>139 pub fn resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error> {
140 self.resolver.resolve_idx(idx, names::Ns::Global)
141 }
142 }
143