1use crate::{
2 BlockId, DeclId, FileId, ModuleId, ParseError, Span, Value, VarId, ast::ImportPatternMember,
3 engine::StateWorkingSet,
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_rows = vec![];
132 let mut errors = vec![];
133
134 decls.extend(self.decls_with_head(&final_name));
135
136 for (name, var_id) in self.consts() {
137 match working_set.get_constant(var_id) {
138 Ok(const_val) => const_rows.push((name, const_val.clone())),
139 Err(err) => errors.push(err),
140 }
141 }
142
143 let span = self.span.unwrap_or(backup_span);
144
145 let constant_values = if const_rows.is_empty() {
147 vec![]
148 } else {
149 vec![(
150 normalize_module_name(&final_name),
151 Value::record(
152 const_rows
153 .into_iter()
154 .map(|(name, val)| (String::from_utf8_lossy(&name).to_string(), val))
155 .collect(),
156 span,
157 ),
158 )]
159 };
160
161 return (
162 ResolvedImportPattern::new(
163 decls,
164 vec![(final_name.clone(), self_id)],
165 vec![],
166 constant_values,
167 ),
168 errors,
169 );
170 };
171
172 match head {
173 ImportPatternMember::Name { name, span } => {
174 let errors = if !rest.is_empty() && self.submodules.get(name).is_none() {
177 vec![ParseError::WrongImportPattern(
178 format!(
179 "Trying to import something but the parent `{}` is not a module, maybe you want to try `use <module> [<name1>, <name2>]`",
180 String::from_utf8_lossy(name)
181 ),
182 rest[0].span(),
183 )]
184 } else {
185 vec![]
186 };
187
188 if name == b"main" {
189 if let Some(main_decl_id) = self.main {
190 (
191 ResolvedImportPattern::new(
192 vec![(final_name, main_decl_id)],
193 vec![],
194 vec![],
195 vec![],
196 ),
197 errors,
198 )
199 } else {
200 (
201 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
202 vec![ParseError::ExportNotFound(*span)],
203 )
204 }
205 } else if let Some(decl_id) = self.decls.get(name) {
206 (
207 ResolvedImportPattern::new(
208 vec![(name.clone(), *decl_id)],
209 vec![],
210 vec![],
211 vec![],
212 ),
213 errors,
214 )
215 } else if let Some(var_id) = self.constants.get(name) {
216 match working_set.get_constant(*var_id) {
217 Ok(_) => (
218 ResolvedImportPattern::new(
219 vec![],
220 vec![],
221 vec![(name.clone(), *var_id)],
222 vec![],
223 ),
224 errors,
225 ),
226 Err(err) => (
227 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
228 vec![err],
229 ),
230 }
231 } else if let Some(submodule_id) = self.submodules.get(name) {
232 let submodule = working_set.get_module(*submodule_id);
233 submodule.resolve_import_pattern(
234 working_set,
235 *submodule_id,
236 rest,
237 None,
238 self.span.unwrap_or(backup_span),
239 imported_modules,
240 )
241 } else {
242 (
243 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
244 vec![ParseError::ExportNotFound(*span)],
245 )
246 }
247 }
248 ImportPatternMember::Glob { .. } => {
249 let mut decls = vec![];
250 let mut submodules = vec![];
251 let mut constants = vec![];
252 let mut constant_values = vec![];
253 let mut errors = vec![];
254
255 for (_, id) in &self.submodules {
256 let submodule = working_set.get_module(*id);
257 let (sub_results, sub_errors) = submodule.resolve_import_pattern(
258 working_set,
259 *id,
260 &[],
261 None,
262 self.span.unwrap_or(backup_span),
263 imported_modules,
264 );
265 decls.extend(sub_results.decls);
266
267 submodules.extend(sub_results.modules);
268 constants.extend(sub_results.constants);
269 constant_values.extend(sub_results.constant_values);
270 errors.extend(sub_errors);
271 }
272
273 decls.extend(self.decls());
274 for (name, var_id) in self.constants.iter() {
275 match working_set.get_constant(*var_id) {
276 Ok(_) => {
277 constants.push((name.clone(), *var_id));
278 }
279 Err(err) => {
280 errors.push(err);
281 }
282 }
283 }
284 submodules.extend(self.submodules());
285
286 (
287 ResolvedImportPattern::new(decls, submodules, constants, constant_values),
288 errors,
289 )
290 }
291 ImportPatternMember::List { names } => {
292 let mut decls = vec![];
293 let mut modules = vec![];
294 let mut constants = vec![];
295 let mut constant_values = vec![];
296 let mut errors = vec![];
297
298 for (name, span) in names {
299 if name == b"main" {
300 if let Some(main_decl_id) = self.main {
301 decls.push((final_name.clone(), main_decl_id));
302 } else {
303 errors.push(ParseError::ExportNotFound(*span));
304 }
305 } else if let Some(decl_id) = self.decls.get(name) {
306 decls.push((name.clone(), *decl_id));
307 } else if let Some(var_id) = self.constants.get(name) {
308 match working_set.get_constant(*var_id) {
309 Ok(_) => constants.push((name.clone(), *var_id)),
310 Err(err) => errors.push(err),
311 }
312 } else if let Some(submodule_id) = self.submodules.get(name) {
313 let submodule = working_set.get_module(*submodule_id);
314 let (sub_results, sub_errors) = submodule.resolve_import_pattern(
315 working_set,
316 *submodule_id,
317 rest,
318 None,
319 self.span.unwrap_or(backup_span),
320 imported_modules,
321 );
322
323 decls.extend(sub_results.decls);
324 modules.extend(sub_results.modules);
325 constants.extend(sub_results.constants);
326 constant_values.extend(sub_results.constant_values);
327 errors.extend(sub_errors);
328 } else {
329 errors.push(ParseError::ExportNotFound(*span));
330 }
331 }
332
333 (
334 ResolvedImportPattern::new(decls, modules, constants, constant_values),
335 errors,
336 )
337 }
338 }
339 }
340
341 pub fn decl_name_with_head(&self, name: &[u8], head: &[u8]) -> Option<Vec<u8>> {
342 if self.has_decl(name) {
343 let mut new_name = head.to_vec();
344 new_name.push(b' ');
345 new_name.extend(name);
346 Some(new_name)
347 } else {
348 None
349 }
350 }
351
352 pub fn decls_with_head(&self, head: &[u8]) -> Vec<(Vec<u8>, DeclId)> {
353 let mut result: Vec<(Vec<u8>, DeclId)> = self
354 .decls
355 .iter()
356 .map(|(name, id)| {
357 let mut new_name = head.to_vec();
358 new_name.push(b' ');
359 new_name.extend(name);
360 (new_name, *id)
361 })
362 .collect();
363
364 if let Some(decl_id) = self.main {
365 result.push((self.name.clone(), decl_id));
366 }
367
368 result
369 }
370
371 pub fn consts(&self) -> Vec<(Vec<u8>, VarId)> {
372 self.constants
373 .iter()
374 .map(|(name, id)| (name.to_vec(), *id))
375 .collect()
376 }
377
378 pub fn decl_names_with_head(&self, head: &[u8]) -> Vec<Vec<u8>> {
379 let mut result: Vec<Vec<u8>> = self
380 .decls
381 .keys()
382 .map(|name| {
383 let mut new_name = head.to_vec();
384 new_name.push(b' ');
385 new_name.extend(name);
386 new_name
387 })
388 .collect();
389
390 if self.main.is_some() {
391 result.push(self.name.clone());
392 }
393
394 result
395 }
396
397 pub fn decls(&self) -> Vec<(Vec<u8>, DeclId)> {
398 let mut result: Vec<(Vec<u8>, DeclId)> = self
399 .decls
400 .iter()
401 .map(|(name, id)| (name.clone(), *id))
402 .collect();
403
404 if let Some(decl_id) = self.main {
405 result.push((self.name.clone(), decl_id));
406 }
407
408 result
409 }
410
411 pub fn submodules(&self) -> Vec<(Vec<u8>, ModuleId)> {
412 self.submodules
413 .iter()
414 .map(|(name, id)| (name.clone(), *id))
415 .collect()
416 }
417
418 pub fn decl_names(&self) -> Vec<Vec<u8>> {
419 let mut result: Vec<Vec<u8>> = self.decls.keys().cloned().collect();
420
421 if self.main.is_some() {
422 result.push(self.name.clone());
423 }
424
425 result
426 }
427}
428
429fn normalize_module_name(bytes: &[u8]) -> Vec<u8> {
431 bytes
432 .iter()
433 .map(|x| match is_identifier_byte(*x) {
434 true => *x,
435 false => b'_',
436 })
437 .collect()
438}
439
440fn is_identifier_byte(b: u8) -> bool {
441 b != b'.'
442 && b != b'['
443 && b != b'('
444 && b != b'{'
445 && b != b'+'
446 && b != b'-'
447 && b != b'*'
448 && b != b'^'
449 && b != b'%'
450 && b != b'/'
451 && b != b'='
452 && b != b'!'
453 && b != b'<'
454 && b != b'>'
455 && b != b'&'
456 && b != b'|'
457}