1use crate::{
2 ast::ImportPatternMember, engine::StateWorkingSet, BlockId, DeclId, FileId, ModuleId,
3 ParseError, Span, Value, VarId,
4};
5
6use crate::parser_path::ParserPath;
7use indexmap::IndexMap;
8
9pub struct ResolvedImportPattern {
10 pub decls: Vec<(Vec<u8>, DeclId)>,
11 pub modules: Vec<(Vec<u8>, ModuleId)>,
12 pub constants: Vec<(Vec<u8>, VarId)>,
13 pub constant_values: Vec<(Vec<u8>, Value)>,
16}
17
18impl ResolvedImportPattern {
19 pub fn new(
20 decls: Vec<(Vec<u8>, DeclId)>,
21 modules: Vec<(Vec<u8>, ModuleId)>,
22 constants: Vec<(Vec<u8>, VarId)>,
23 constant_values: Vec<(Vec<u8>, Value)>,
24 ) -> Self {
25 ResolvedImportPattern {
26 decls,
27 modules,
28 constants,
29 constant_values,
30 }
31 }
32}
33
34#[derive(Debug, Clone)]
36pub struct Module {
37 pub name: Vec<u8>,
38 pub decls: IndexMap<Vec<u8>, DeclId>,
39 pub submodules: IndexMap<Vec<u8>, ModuleId>,
40 pub constants: IndexMap<Vec<u8>, VarId>,
41 pub env_block: Option<BlockId>, pub main: Option<DeclId>, pub span: Option<Span>,
44 pub imported_modules: Vec<ModuleId>, pub file: Option<(ParserPath, FileId)>,
46}
47
48impl Module {
49 pub fn new(name: Vec<u8>) -> Self {
50 Module {
51 name,
52 decls: IndexMap::new(),
53 submodules: IndexMap::new(),
54 constants: IndexMap::new(),
55 env_block: None,
56 main: None,
57 span: None,
58 imported_modules: vec![],
59 file: None,
60 }
61 }
62
63 pub fn from_span(name: Vec<u8>, span: Span) -> Self {
64 Module {
65 name,
66 decls: IndexMap::new(),
67 submodules: IndexMap::new(),
68 constants: IndexMap::new(),
69 env_block: None,
70 main: None,
71 span: Some(span),
72 imported_modules: vec![],
73 file: None,
74 }
75 }
76
77 pub fn name(&self) -> Vec<u8> {
78 self.name.clone()
79 }
80
81 pub fn add_decl(&mut self, name: Vec<u8>, decl_id: DeclId) -> Option<DeclId> {
82 self.decls.insert(name, decl_id)
83 }
84
85 pub fn add_submodule(&mut self, name: Vec<u8>, module_id: ModuleId) -> Option<ModuleId> {
86 self.submodules.insert(name, module_id)
87 }
88
89 pub fn add_variable(&mut self, name: Vec<u8>, var_id: VarId) -> Option<VarId> {
90 self.constants.insert(name, var_id)
91 }
92
93 pub fn add_env_block(&mut self, block_id: BlockId) {
94 self.env_block = Some(block_id);
95 }
96
97 pub fn track_imported_modules(&mut self, module_id: &[ModuleId]) {
98 for m in module_id {
99 self.imported_modules.push(*m)
100 }
101 }
102
103 pub fn has_decl(&self, name: &[u8]) -> bool {
104 if name == self.name && self.main.is_some() {
105 return true;
106 }
107
108 self.decls.contains_key(name)
109 }
110
111 pub fn resolve_import_pattern(
115 &self,
116 working_set: &StateWorkingSet,
117 self_id: ModuleId,
118 members: &[ImportPatternMember],
119 name_override: Option<&[u8]>, backup_span: Span,
121 imported_modules: &mut Vec<ModuleId>,
122 ) -> (ResolvedImportPattern, Vec<ParseError>) {
123 imported_modules.push(self_id);
124 let final_name = name_override.unwrap_or(&self.name).to_vec();
125
126 let (head, rest) = if let Some((head, rest)) = members.split_first() {
127 (head, rest)
128 } else {
129 let mut decls = vec![];
131 let mut const_vids = vec![];
132 let mut const_rows = vec![];
133 let mut errors = vec![];
134
135 for (_, id) in &self.submodules {
136 let submodule = working_set.get_module(*id);
137 let span = submodule.span.or(self.span).unwrap_or(backup_span);
138
139 let (sub_results, sub_errors) = submodule.resolve_import_pattern(
140 working_set,
141 *id,
142 &[],
143 None,
144 span,
145 imported_modules,
146 );
147 errors.extend(sub_errors);
148
149 for (sub_name, sub_decl_id) in sub_results.decls {
150 let mut new_name = final_name.clone();
151 new_name.push(b' ');
152 new_name.extend(sub_name);
153
154 decls.push((new_name, sub_decl_id));
155 }
156
157 const_vids.extend(sub_results.constants);
158 const_rows.extend(sub_results.constant_values);
159 }
160
161 decls.extend(self.decls_with_head(&final_name));
162
163 for (name, var_id) in self.consts() {
164 match working_set.get_constant(var_id) {
165 Ok(const_val) => {
166 const_vids.push((name.clone(), var_id));
167 const_rows.push((name, const_val.clone()))
168 }
169 Err(err) => errors.push(err),
170 }
171 }
172
173 let span = self.span.unwrap_or(backup_span);
174
175 let constant_values = if const_rows.is_empty() {
177 vec![]
178 } else {
179 vec![(
180 normalize_module_name(&final_name),
181 Value::record(
182 const_rows
183 .into_iter()
184 .map(|(name, val)| (String::from_utf8_lossy(&name).to_string(), val))
185 .collect(),
186 span,
187 ),
188 )]
189 };
190
191 return (
192 ResolvedImportPattern::new(
193 decls,
194 vec![(final_name.clone(), self_id)],
195 const_vids,
196 constant_values,
197 ),
198 errors,
199 );
200 };
201
202 match head {
203 ImportPatternMember::Name { name, span } => {
204 let errors = if !rest.is_empty() && self.submodules.get(name).is_none() {
207 vec![ParseError::WrongImportPattern(
208 format!("Trying to import something but the parent `{}` is not a module, maybe you want to try `use <module> [<name1>, <name2>]`", String::from_utf8_lossy(name)),
209 rest[0].span(),
210 )]
211 } else {
212 vec![]
213 };
214
215 if name == b"main" {
216 if let Some(main_decl_id) = self.main {
217 (
218 ResolvedImportPattern::new(
219 vec![(final_name, main_decl_id)],
220 vec![],
221 vec![],
222 vec![],
223 ),
224 errors,
225 )
226 } else {
227 (
228 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
229 vec![ParseError::ExportNotFound(*span)],
230 )
231 }
232 } else if let Some(decl_id) = self.decls.get(name) {
233 (
234 ResolvedImportPattern::new(
235 vec![(name.clone(), *decl_id)],
236 vec![],
237 vec![],
238 vec![],
239 ),
240 errors,
241 )
242 } else if let Some(var_id) = self.constants.get(name) {
243 match working_set.get_constant(*var_id) {
244 Ok(_) => (
245 ResolvedImportPattern::new(
246 vec![],
247 vec![],
248 vec![(name.clone(), *var_id)],
249 vec![],
250 ),
251 errors,
252 ),
253 Err(err) => (
254 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
255 vec![err],
256 ),
257 }
258 } else if let Some(submodule_id) = self.submodules.get(name) {
259 let submodule = working_set.get_module(*submodule_id);
260 submodule.resolve_import_pattern(
261 working_set,
262 *submodule_id,
263 rest,
264 None,
265 self.span.unwrap_or(backup_span),
266 imported_modules,
267 )
268 } else {
269 (
270 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
271 vec![ParseError::ExportNotFound(*span)],
272 )
273 }
274 }
275 ImportPatternMember::Glob { .. } => {
276 let mut decls = vec![];
277 let mut submodules = vec![];
278 let mut constants = vec![];
279 let mut constant_values = vec![];
280 let mut errors = vec![];
281
282 for (_, id) in &self.submodules {
283 let submodule = working_set.get_module(*id);
284 let (sub_results, sub_errors) = submodule.resolve_import_pattern(
285 working_set,
286 *id,
287 &[],
288 None,
289 self.span.unwrap_or(backup_span),
290 imported_modules,
291 );
292 decls.extend(sub_results.decls);
293
294 submodules.extend(sub_results.modules);
295 constants.extend(sub_results.constants);
296 constant_values.extend(sub_results.constant_values);
297 errors.extend(sub_errors);
298 }
299
300 decls.extend(self.decls());
301 for (name, var_id) in self.constants.iter() {
302 match working_set.get_constant(*var_id) {
303 Ok(_) => {
304 constants.push((name.clone(), *var_id));
305 }
306 Err(err) => {
307 errors.push(err);
308 }
309 }
310 }
311 submodules.extend(self.submodules());
312
313 (
314 ResolvedImportPattern::new(decls, submodules, constants, constant_values),
315 errors,
316 )
317 }
318 ImportPatternMember::List { names } => {
319 let mut decls = vec![];
320 let mut modules = vec![];
321 let mut constants = vec![];
322 let mut constant_values = vec![];
323 let mut errors = vec![];
324
325 for (name, span) in names {
326 if name == b"main" {
327 if let Some(main_decl_id) = self.main {
328 decls.push((final_name.clone(), main_decl_id));
329 } else {
330 errors.push(ParseError::ExportNotFound(*span));
331 }
332 } else if let Some(decl_id) = self.decls.get(name) {
333 decls.push((name.clone(), *decl_id));
334 } else if let Some(var_id) = self.constants.get(name) {
335 match working_set.get_constant(*var_id) {
336 Ok(_) => constants.push((name.clone(), *var_id)),
337 Err(err) => errors.push(err),
338 }
339 } else if let Some(submodule_id) = self.submodules.get(name) {
340 let submodule = working_set.get_module(*submodule_id);
341 let (sub_results, sub_errors) = submodule.resolve_import_pattern(
342 working_set,
343 *submodule_id,
344 rest,
345 None,
346 self.span.unwrap_or(backup_span),
347 imported_modules,
348 );
349
350 decls.extend(sub_results.decls);
351 modules.extend(sub_results.modules);
352 constants.extend(sub_results.constants);
353 constant_values.extend(sub_results.constant_values);
354 errors.extend(sub_errors);
355 } else {
356 errors.push(ParseError::ExportNotFound(*span));
357 }
358 }
359
360 (
361 ResolvedImportPattern::new(decls, modules, constants, constant_values),
362 errors,
363 )
364 }
365 }
366 }
367
368 pub fn decl_name_with_head(&self, name: &[u8], head: &[u8]) -> Option<Vec<u8>> {
369 if self.has_decl(name) {
370 let mut new_name = head.to_vec();
371 new_name.push(b' ');
372 new_name.extend(name);
373 Some(new_name)
374 } else {
375 None
376 }
377 }
378
379 pub fn decls_with_head(&self, head: &[u8]) -> Vec<(Vec<u8>, DeclId)> {
380 let mut result: Vec<(Vec<u8>, DeclId)> = self
381 .decls
382 .iter()
383 .map(|(name, id)| {
384 let mut new_name = head.to_vec();
385 new_name.push(b' ');
386 new_name.extend(name);
387 (new_name, *id)
388 })
389 .collect();
390
391 if let Some(decl_id) = self.main {
392 result.push((self.name.clone(), decl_id));
393 }
394
395 result
396 }
397
398 pub fn consts(&self) -> Vec<(Vec<u8>, VarId)> {
399 self.constants
400 .iter()
401 .map(|(name, id)| (name.to_vec(), *id))
402 .collect()
403 }
404
405 pub fn decl_names_with_head(&self, head: &[u8]) -> Vec<Vec<u8>> {
406 let mut result: Vec<Vec<u8>> = self
407 .decls
408 .keys()
409 .map(|name| {
410 let mut new_name = head.to_vec();
411 new_name.push(b' ');
412 new_name.extend(name);
413 new_name
414 })
415 .collect();
416
417 if self.main.is_some() {
418 result.push(self.name.clone());
419 }
420
421 result
422 }
423
424 pub fn decls(&self) -> Vec<(Vec<u8>, DeclId)> {
425 let mut result: Vec<(Vec<u8>, DeclId)> = self
426 .decls
427 .iter()
428 .map(|(name, id)| (name.clone(), *id))
429 .collect();
430
431 if let Some(decl_id) = self.main {
432 result.push((self.name.clone(), decl_id));
433 }
434
435 result
436 }
437
438 pub fn submodules(&self) -> Vec<(Vec<u8>, ModuleId)> {
439 self.submodules
440 .iter()
441 .map(|(name, id)| (name.clone(), *id))
442 .collect()
443 }
444
445 pub fn decl_names(&self) -> Vec<Vec<u8>> {
446 let mut result: Vec<Vec<u8>> = self.decls.keys().cloned().collect();
447
448 if self.main.is_some() {
449 result.push(self.name.clone());
450 }
451
452 result
453 }
454}
455
456fn normalize_module_name(bytes: &[u8]) -> Vec<u8> {
458 bytes
459 .iter()
460 .map(|x| match is_identifier_byte(*x) {
461 true => *x,
462 false => b'_',
463 })
464 .collect()
465}
466
467fn is_identifier_byte(b: u8) -> bool {
468 b != b'.'
469 && b != b'['
470 && b != b'('
471 && b != b'{'
472 && b != b'+'
473 && b != b'-'
474 && b != b'*'
475 && b != b'^'
476 && b != b'/'
477 && b != b'='
478 && b != b'!'
479 && b != b'<'
480 && b != b'>'
481 && b != b'&'
482 && b != b'|'
483}