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); 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(), 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 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 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 self.resolved_types.insert(type_id, rtype);
279 let import_item_id = ImportItemId::Type(rtype);
281 self.items.push(import_item_id);
282 rtype
283 }
284}