| 1 | use crate::core::*; |
| 2 | use crate::token::Index; |
| 3 | use crate::{gensym, Error}; |
| 4 | |
| 5 | mod deinline_import_export; |
| 6 | mod names; |
| 7 | pub(crate) mod types; |
| 8 | |
| 9 | #[cfg (feature = "component-model" )] |
| 10 | pub(crate) use names::ResolveCoreType; |
| 11 | |
| 12 | #[derive (PartialEq, Eq, Hash, Copy, Clone, Debug)] |
| 13 | pub enum Ns { |
| 14 | Func, |
| 15 | Table, |
| 16 | Global, |
| 17 | Memory, |
| 18 | Tag, |
| 19 | Type, |
| 20 | } |
| 21 | |
| 22 | pub 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)] |
| 68 | pub struct Names<'a> { |
| 69 | resolver: names::Resolver<'a>, |
| 70 | } |
| 71 | |
| 72 | impl<'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 | |