claw_resolver/
imports.rs

1use std::collections::HashMap;
2
3use ast::NameId;
4use claw_ast as ast;
5
6use crate::types::ResolvedType;
7use crate::wit::{self, InterfaceId};
8use crate::ResolverError;
9use cranelift_entity::{entity_impl, PrimaryMap};
10
11#[derive(Default)]
12pub struct ImportResolver {
13    pub mapping: HashMap<String, ImportItemId>,
14    pub types: PrimaryMap<ImportTypeId, ImportType>,
15    pub funcs: PrimaryMap<ImportFuncId, ImportFunction>,
16
17    pub interfaces: Vec<ResolvedInterface>,
18    pub loose_funcs: Vec<ImportFuncId>,
19}
20
21#[derive(Copy, Clone, Debug)]
22pub enum ImportItemId {
23    Type(ResolvedType),
24    Func(ImportFuncId),
25}
26
27#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
28pub struct ImportFuncId(u32);
29entity_impl!(ImportFuncId, "import-func");
30
31#[derive(Clone, Debug)]
32pub struct ImportFunction {
33    pub alias: String,
34    pub name: String,
35    pub params: Vec<(String, ResolvedType)>,
36    pub results: Option<ResolvedType>,
37}
38
39#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
40pub struct ImportTypeId(u32);
41entity_impl!(ImportTypeId, "import-type");
42
43pub enum ImportType {
44    Enum(ImportEnum),
45}
46
47pub struct ImportEnum {
48    pub name: String,
49    pub cases: Vec<String>,
50}
51
52impl ImportResolver {
53    pub fn resolve_imports(
54        &mut self,
55        comp: &ast::Component,
56        wit: &wit::ResolvedWit,
57    ) -> Result<(), ResolverError> {
58        for (_, import) in comp.imports.iter() {
59            match import {
60                ast::Import::Plain(import) => {
61                    self.resolve_plain_import(import, comp);
62                }
63                ast::Import::ImportFrom(import) => {
64                    self.resolve_import_from(import, comp, wit)?;
65                }
66            }
67        }
68        Ok(())
69    }
70
71    pub fn resolve_plain_import(&mut self, import: &ast::PlainImport, comp: &ast::Component) {
72        match &import.external_type {
73            ast::ExternalType::Function(fn_type) => {
74                self.resolve_plain_import_func(import.ident, import.alias, fn_type, comp);
75            }
76        };
77    }
78
79    fn resolve_plain_import_func(
80        &mut self,
81        name: NameId,
82        alias: Option<NameId>,
83        fn_type: &ast::FnType,
84        comp: &ast::Component,
85    ) {
86        let name = comp.get_name(name);
87
88        let params = fn_type
89            .params
90            .iter()
91            .map(|(name, type_id)| {
92                let name = comp.get_name(*name).to_owned();
93                (name, ResolvedType::Defined(*type_id))
94            })
95            .collect();
96
97        let results = fn_type.results.map(ResolvedType::Defined);
98
99        let alias = match alias {
100            Some(alias) => comp.get_name(alias),
101            None => name,
102        };
103        let import_func = ImportFunction {
104            alias: alias.to_owned(),
105            name: name.to_owned(),
106            params,
107            results,
108        };
109
110        let import_func_id = self.funcs.push(import_func);
111        let import_item_id = ImportItemId::Func(import_func_id);
112        self.mapping.insert(alias.to_owned(), import_item_id);
113        self.loose_funcs.push(import_func_id);
114    }
115
116    pub fn resolve_import_from(
117        &mut self,
118        import: &ast::ImportFrom,
119        comp: &ast::Component,
120        wit: &wit::ResolvedWit,
121    ) -> Result<(), ResolverError> {
122        let interface_id = wit.lookup_interface(&import.package, &import.interface)?;
123
124        let mut resolver = InterfaceResolver::new(interface_id, self, wit);
125        let mut bindings = Vec::new();
126        for (name, alias) in import.items.iter() {
127            let name = comp.get_name(*name);
128            let item_id = resolver.resolve_name(name).unwrap();
129            let name = match alias {
130                Some(name) => comp.get_name(*name).to_owned(),
131                None => name.to_owned(),
132            };
133            bindings.push((name, item_id));
134        }
135
136        let resolved = resolver.finalize();
137        self.interfaces.push(resolved);
138
139        for (name, item) in bindings {
140            self.mapping.insert(name, item);
141        }
142
143        Ok(())
144    }
145}
146
147pub struct InterfaceResolver<'ctx> {
148    wit: &'ctx wit::ResolvedWit,
149    imports: &'ctx mut ImportResolver,
150
151    interface_id: InterfaceId,
152    interface: &'ctx wit::Interface,
153
154    resolved_types: HashMap<wit::TypeId, ResolvedType>,
155    items: Vec<ImportItemId>,
156}
157
158pub struct ResolvedInterface {
159    pub interface_id: InterfaceId,
160    pub name: String,
161    pub items: Vec<ImportItemId>,
162}
163
164impl<'ctx> InterfaceResolver<'ctx> {
165    pub fn new(
166        interface_id: InterfaceId,
167        imports: &'ctx mut ImportResolver,
168        wit: &'ctx wit::ResolvedWit,
169    ) -> Self {
170        let interface = wit.get_interface(interface_id);
171
172        Self {
173            wit,
174            imports,
175            interface_id,
176            interface,
177            resolved_types: Default::default(),
178            items: Default::default(),
179        }
180    }
181
182    pub fn finalize(self) -> ResolvedInterface {
183        ResolvedInterface {
184            interface_id: self.interface_id,
185            name: self.wit.resolve.id_of(self.interface_id).unwrap(),
186            items: self.items,
187        }
188    }
189
190    pub fn resolve_name(&mut self, name: &str) -> Option<ImportItemId> {
191        if let Some(func) = self.interface.functions.get(name) {
192            return Some(self.resolve_import_func(name, func));
193        }
194        if let Some(type_id) = self.interface.types.get(name) {
195            return Some(ImportItemId::Type(self.resolve_type_id(*type_id)));
196        }
197        None
198    }
199
200    fn resolve_import_func(&mut self, name: &str, func: &wit::Function) -> ImportItemId {
201        let mut params = Vec::new();
202        for (param_name, param_type) in func.params.iter() {
203            let rtype = self.resolve_type(param_type);
204            params.push((param_name.clone(), rtype));
205        }
206
207        let results = match &func.results {
208            wit_parser::Results::Named(named_types) => {
209                assert_eq!(named_types.len(), 0); // Can only handle "empty" named types
210                None
211            }
212            wit_parser::Results::Anon(result_type) => Some(self.resolve_type(result_type)),
213        };
214
215        let import_func = ImportFunction {
216            alias: name.to_owned(), // TODO fix
217            name: name.to_owned(),
218            params,
219            results,
220        };
221        let import_func_id = self.imports.funcs.push(import_func);
222        self.items.push(ImportItemId::Func(import_func_id));
223        ImportItemId::Func(import_func_id)
224    }
225
226    fn resolve_type(&mut self, type_: &wit::Type) -> ResolvedType {
227        type PType = ast::PrimitiveType;
228        match type_ {
229            // Primitives
230            wit::Type::Bool => ResolvedType::Primitive(PType::Bool),
231            wit::Type::U8 => ResolvedType::Primitive(PType::U8),
232            wit::Type::U16 => ResolvedType::Primitive(PType::U16),
233            wit::Type::U32 => ResolvedType::Primitive(PType::U32),
234            wit::Type::U64 => ResolvedType::Primitive(PType::U64),
235            wit::Type::S8 => ResolvedType::Primitive(PType::S8),
236            wit::Type::S16 => ResolvedType::Primitive(PType::S16),
237            wit::Type::S32 => ResolvedType::Primitive(PType::S32),
238            wit::Type::S64 => ResolvedType::Primitive(PType::S64),
239            wit::Type::F32 => ResolvedType::Primitive(PType::F32),
240            wit::Type::F64 => ResolvedType::Primitive(PType::F64),
241            wit::Type::Char => todo!(),
242            wit::Type::String => ResolvedType::Primitive(PType::String),
243            wit::Type::Id(id) => {
244                if let Some(rtype) = self.resolved_types.get(id) {
245                    *rtype
246                } else {
247                    self.resolve_type_id(*id)
248                }
249            }
250        }
251    }
252
253    fn resolve_type_id(&mut self, type_id: wit::TypeId) -> ResolvedType {
254        let type_def = self.wit.resolve.types.get(type_id).unwrap();
255        let name = type_def.name.as_ref().unwrap().to_owned();
256        assert_eq!(type_def.owner, wit::TypeOwner::Interface(self.interface_id));
257        // Construct the ImportType
258        let rtype = match &type_def.kind {
259            wit::TypeDefKind::Enum(enum_type) => {
260                let name = name.clone();
261                let cases = enum_type
262                    .cases
263                    .iter()
264                    .map(|case| &case.name)
265                    .cloned()
266                    .collect();
267                let import_enum = ImportEnum { name, cases };
268                let import_type = ImportType::Enum(import_enum);
269                let import_type_id = self.imports.types.push(import_type);
270                ResolvedType::Import(import_type_id)
271            }
272            wit::TypeDefKind::Type(t) => {
273                return self.resolve_type(t);
274            }
275            a => panic!("Unsupported import type kind {:?}", a),
276        };
277        // Record item id and resolved type
278        self.resolved_types.insert(type_id, rtype);
279        // Record item in interface ordering
280        let import_item_id = ImportItemId::Type(rtype);
281        self.items.push(import_item_id);
282        rtype
283    }
284}