1use crate::core::*;
2use crate::token::Index;
3use crate::{gensym, Error};
4
5mod deinline_import_export;
6mod names;
7pub(crate) mod types;
8
9#[cfg(feature = "component-model")]
10pub(crate) use names::ResolveCoreType;
11
12#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
13pub enum Ns {
14 Func,
15 Table,
16 Global,
17 Memory,
18 Tag,
19 Type,
20}
21
22pub fn resolve<'a>(fields: &mut Vec<ModuleField<'a>>) -> Result<Names<'a>, Error> {
23 // Ensure that each resolution of a module is deterministic in the names
24 // that it generates by resetting our thread-local symbol generator.
25 gensym::reset();
26
27 // First up, de-inline import/export annotations.
28 //
29 // This ensures we only have to deal with inline definitions and to
30 // calculate exports we only have to look for a particular kind of module
31 // field.
32 deinline_import_export::run(fields);
33
34 // With a canonical form of imports make sure that imports are all listed
35 // first.
36 let mut last = None;
37 for field in fields.iter() {
38 match field {
39 ModuleField::Import(i) => {
40 if let Some(name) = last {
41 return Err(Error::new(i.span, format!("import after {}", name)));
42 }
43 }
44 ModuleField::Memory(_) => last = Some("memory"),
45 ModuleField::Func(_) => last = Some("function"),
46 ModuleField::Table(_) => last = Some("table"),
47 ModuleField::Global(_) => last = Some("global"),
48 _ => continue,
49 }
50 }
51
52 // Expand all `TypeUse` annotations so all necessary `type` nodes are
53 // present in the AST.
54 types::expand(fields);
55
56 // Perform name resolution over all `Index` items to resolve them all to
57 // indices instead of symbolic names.
58 let resolver = names::resolve(fields)?;
59 Ok(Names { resolver })
60}
61
62/// Representation of the results of name resolution for a module.
63///
64/// This structure is returned from the
65/// [`Module::resolve`](crate::core::Module::resolve) function and can be used
66/// to resolve your own name arguments if you have any.
67#[derive(Default)]
68pub struct Names<'a> {
69 resolver: names::Resolver<'a>,
70}
71
72impl<'a> Names<'a> {
73 /// Resolves `idx` within the function namespace.
74 ///
75 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
76 /// looked up in the function namespace and converted to a `Num`. If the
77 /// `Id` is not defined then an error will be returned.
78 pub fn resolve_func(&self, idx: &mut Index<'a>) -> Result<(), Error> {
79 self.resolver.resolve(idx, Ns::Func)?;
80 Ok(())
81 }
82
83 /// Resolves `idx` within the memory namespace.
84 ///
85 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
86 /// looked up in the memory namespace and converted to a `Num`. If the
87 /// `Id` is not defined then an error will be returned.
88 pub fn resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error> {
89 self.resolver.resolve(idx, Ns::Memory)?;
90 Ok(())
91 }
92
93 /// Resolves `idx` within the table namespace.
94 ///
95 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
96 /// looked up in the table namespace and converted to a `Num`. If the
97 /// `Id` is not defined then an error will be returned.
98 pub fn resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error> {
99 self.resolver.resolve(idx, Ns::Table)?;
100 Ok(())
101 }
102
103 /// Resolves `idx` within the global namespace.
104 ///
105 /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
106 /// looked up in the global namespace and converted to a `Num`. If the
107 /// `Id` is not defined then an error will be returned.
108 pub fn resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error> {
109 self.resolver.resolve(idx, Ns::Global)?;
110 Ok(())
111 }
112}
113