1use crate::{
2 BlockId, Category, CompileError, Config, DeclId, FileId, GetSpan, Module, ModuleId, OverlayId,
3 ParseError, ParseWarning, ResolvedImportPattern, ResolvedSpan, Signature, Span, SpanId, Type,
4 Value, VarId, VirtualPathId,
5 ast::Block,
6 engine::{
7 CachedFile, Command, CommandType, EngineState, OverlayFrame, ScopeBindings, StateDelta,
8 Variable, VirtualPath, Visibility, VisibilityStack, description::build_desc,
9 },
10};
11use core::panic;
12use std::{
13 collections::{HashMap, HashSet},
14 path::{Path, PathBuf},
15 sync::{Arc, Mutex},
16};
17
18#[cfg(feature = "plugin")]
19use crate::{PluginIdentity, PluginRegistryItem, RegisteredPlugin};
20
21pub struct StateWorkingSet<'a> {
27 pub permanent_state: &'a EngineState,
28 pub delta: StateDelta,
29 pub files: FileStack,
30 pub search_predecls: bool,
32 pub skip_module_load: bool,
37 pub parse_errors: Vec<ParseError>,
38 pub parse_warnings: Vec<ParseWarning>,
39 pub compile_errors: Vec<CompileError>,
40 permanent_signatures: Mutex<HashMap<DeclId, Arc<Signature>>>,
58 permanent_decl_signatures: Mutex<HashMap<DeclId, Arc<Signature>>>,
59}
60
61impl<'a> StateWorkingSet<'a> {
62 pub fn new(permanent_state: &'a EngineState) -> Self {
63 let files = if let Some(file) = permanent_state.file.clone() {
65 FileStack::with_file(file)
66 } else {
67 FileStack::new()
68 };
69
70 Self {
71 delta: StateDelta::new(permanent_state),
72 permanent_state,
73 files,
74 search_predecls: true,
75 skip_module_load: false,
76 parse_errors: vec![],
77 parse_warnings: vec![],
78 compile_errors: vec![],
79 permanent_signatures: Mutex::new(HashMap::new()),
80 permanent_decl_signatures: Mutex::new(HashMap::new()),
81 }
82 }
83
84 pub fn permanent(&self) -> &EngineState {
85 self.permanent_state
86 }
87
88 pub fn error(&mut self, parse_error: ParseError) {
89 self.parse_errors.push(parse_error)
90 }
91
92 pub fn warning(&mut self, parse_warning: ParseWarning) {
93 self.parse_warnings.push(parse_warning)
94 }
95
96 pub fn num_files(&self) -> usize {
97 self.delta.num_files() + self.permanent_state.num_files()
98 }
99
100 pub fn num_virtual_paths(&self) -> usize {
101 self.delta.num_virtual_paths() + self.permanent_state.num_virtual_paths()
102 }
103
104 pub fn num_vars(&self) -> usize {
105 self.delta.num_vars() + self.permanent_state.num_vars()
106 }
107
108 pub fn num_decls(&self) -> usize {
109 self.delta.num_decls() + self.permanent_state.num_decls()
110 }
111
112 pub fn num_blocks(&self) -> usize {
113 self.delta.num_blocks() + self.permanent_state.num_blocks()
114 }
115
116 pub fn num_modules(&self) -> usize {
117 self.delta.num_modules() + self.permanent_state.num_modules()
118 }
119
120 pub fn unique_overlay_names(&self) -> HashSet<&[u8]> {
121 let mut names: HashSet<&[u8]> = self.permanent_state.active_overlay_names(&[]).collect();
122
123 for scope_frame in self.delta.scope.iter().rev() {
124 for overlay_id in scope_frame.active_overlays.iter().rev() {
125 let (overlay_name, _) = scope_frame
126 .overlays
127 .get(overlay_id.get())
128 .expect("internal error: missing overlay");
129
130 names.insert(overlay_name);
131 names.retain(|n| !scope_frame.removed_overlays.iter().any(|m| n == m));
132 }
133 }
134
135 names
136 }
137
138 pub fn num_overlays(&self) -> usize {
139 self.unique_overlay_names().len()
140 }
141
142 pub fn add_decl(&mut self, decl: Box<dyn Command>) -> DeclId {
143 let name = decl.name().as_bytes().to_vec();
144
145 self.delta.decls.push(decl);
146 let decl_id = self.num_decls() - 1;
147 let decl_id = DeclId::new(decl_id);
148
149 self.last_overlay_mut().insert_decl(name, decl_id);
150
151 decl_id
152 }
153
154 pub fn use_decls(&mut self, decls: Vec<(Vec<u8>, DeclId)>) {
155 let overlay_frame = self.last_overlay_mut();
156
157 for (name, decl_id) in decls {
158 overlay_frame.insert_decl(name, decl_id);
159 overlay_frame.visibility.use_decl_id(&decl_id);
160 }
161 }
162
163 pub fn use_modules(&mut self, modules: Vec<(Vec<u8>, ModuleId)>) {
164 let overlay_frame = self.last_overlay_mut();
165
166 for (name, module_id) in modules {
167 overlay_frame.insert_module(name, module_id);
168 }
170 }
171
172 pub fn use_variables(&mut self, variables: Vec<(Vec<u8>, VarId)>) {
173 for (name, var_id) in variables {
174 self.insert_variable_into_scope(name, var_id);
175 }
176 }
177
178 pub fn add_predecl(&mut self, decl: Box<dyn Command>) -> Option<DeclId> {
179 let name = decl.name().as_bytes().to_vec();
180
181 self.delta.decls.push(decl);
182 let decl_id = self.num_decls() - 1;
183 let decl_id = DeclId::new(decl_id);
184
185 self.delta
186 .last_scope_frame_mut()
187 .predecls
188 .insert(name, decl_id)
189 }
190
191 #[cfg(feature = "plugin")]
192 pub fn find_or_create_plugin(
193 &mut self,
194 identity: &PluginIdentity,
195 make: impl FnOnce() -> Arc<dyn RegisteredPlugin>,
196 ) -> Arc<dyn RegisteredPlugin> {
197 if let Some(plugin) = self
199 .delta
200 .plugins
201 .iter()
202 .chain(self.permanent_state.plugins())
203 .find(|p| p.identity() == identity)
204 {
205 plugin.clone()
206 } else {
207 let plugin = make();
208 self.delta.plugins.push(plugin.clone());
209 plugin
210 }
211 }
212
213 #[cfg(feature = "plugin")]
214 pub fn update_plugin_registry(&mut self, item: PluginRegistryItem) {
215 self.delta.plugin_registry_items.push(item);
216 }
217
218 pub fn merge_predecl(&mut self, name: &[u8]) -> Option<DeclId> {
219 self.move_one_predecl_to_overlay(name);
220
221 let overlay_frame = self.last_overlay_mut();
222
223 if let Some(decl_id) = overlay_frame.predecls.remove(name) {
224 overlay_frame.insert_decl(name.into(), decl_id);
225
226 return Some(decl_id);
227 }
228
229 None
230 }
231
232 fn move_one_predecl_to_overlay(&mut self, name: &[u8]) {
233 self.delta
234 .last_scope_frame_mut()
235 .predecls
236 .remove_entry(name)
237 .map(|(name, decl_id)| self.last_overlay_mut().predecls.insert(name, decl_id));
238 }
239
240 pub fn hide_decl(&mut self, name: &[u8]) -> Option<DeclId> {
241 let mut removed_overlays = vec![];
242 let mut visibility: Visibility = Visibility::new();
243
244 for scope_frame in self.delta.scope.iter_mut().rev() {
246 for overlay_id in scope_frame
247 .active_overlay_ids(&mut removed_overlays)
248 .iter()
249 .rev()
250 {
251 let overlay_frame = scope_frame.get_overlay_mut(*overlay_id);
252
253 visibility.append(&overlay_frame.visibility);
254
255 if let Some(decl_id) = overlay_frame.get_decl(name)
256 && visibility.is_decl_id_visible(&decl_id)
257 {
258 overlay_frame.visibility.hide_decl_id(&decl_id);
260 return Some(decl_id);
261 }
262 }
263 }
264
265 for overlay_frame in self
268 .permanent_state
269 .active_overlays(&removed_overlays)
270 .rev()
271 {
272 visibility.append(&overlay_frame.visibility);
273
274 if let Some(decl_id) = overlay_frame.get_decl(name)
275 && visibility.is_decl_id_visible(&decl_id)
276 {
277 self.last_overlay_mut().visibility.hide_decl_id(&decl_id);
279 return Some(decl_id);
280 }
281 }
282
283 None
284 }
285
286 pub fn hide_decls(&mut self, decls: &[Vec<u8>]) {
287 for decl in decls.iter() {
288 self.hide_decl(decl); }
290 }
291
292 pub fn add_block(&mut self, block: Arc<Block>) -> BlockId {
293 log::trace!(
294 "block id={} added, has IR = {:?}",
295 self.num_blocks(),
296 block.ir_block.is_some()
297 );
298
299 self.delta.blocks.push(block);
300
301 BlockId::new(self.num_blocks() - 1)
302 }
303
304 pub fn add_module(&mut self, name: &str, module: Module, comments: Vec<Span>) -> ModuleId {
305 let name = name.as_bytes().to_vec();
306
307 self.delta.modules.push(Arc::new(module));
308 let module_id = self.num_modules() - 1;
309 let module_id = ModuleId::new(module_id);
310
311 if !comments.is_empty() {
312 self.delta
313 .doccomments
314 .add_module_comments(module_id, comments);
315 }
316
317 self.last_overlay_mut().modules.insert(name, module_id);
318
319 module_id
320 }
321
322 pub fn get_module_comments(&self, module_id: ModuleId) -> Option<&[Span]> {
323 self.delta
324 .doccomments
325 .get_module_comments(module_id)
326 .or_else(|| self.permanent_state.get_module_comments(module_id))
327 }
328
329 pub fn next_span_start(&self) -> usize {
330 let permanent_span_start = self.permanent_state.next_span_start();
331
332 if let Some(cached_file) = self.delta.files.last() {
333 cached_file.covered_span.end
334 } else {
335 permanent_span_start
336 }
337 }
338
339 pub fn files(&self) -> impl DoubleEndedIterator<Item = &CachedFile> {
340 self.permanent_state.files().chain(self.delta.files.iter())
341 }
342
343 pub fn get_contents_of_file(&self, file_id: FileId) -> Option<&[u8]> {
344 if let Some(cached_file) = self.permanent_state.get_file_contents().get(file_id.get()) {
345 return Some(&cached_file.content);
346 }
347 if let Some(cached_file) = self
350 .delta
351 .get_file_contents()
352 .get(file_id.get() - self.permanent_state.num_files())
353 {
354 return Some(&cached_file.content);
355 }
356
357 None
358 }
359
360 #[must_use]
361 pub fn add_file(&mut self, filename: &str, contents: &[u8]) -> FileId {
362 for (idx, cached_file) in self.files().enumerate() {
364 if &*cached_file.name == filename && &*cached_file.content == contents {
365 return FileId::new(idx);
366 }
367 }
368
369 let next_span_start = self.next_span_start();
370 let next_span_end = next_span_start + contents.len();
371
372 let covered_span = Span::new(next_span_start, next_span_end);
373
374 self.delta.files.push(CachedFile {
375 name: filename.into(),
376 content: contents.into(),
377 covered_span,
378 });
379
380 FileId::new(self.num_files() - 1)
381 }
382
383 #[must_use]
384 pub fn add_virtual_path(&mut self, name: String, virtual_path: VirtualPath) -> VirtualPathId {
385 self.delta.virtual_paths.push((name, virtual_path));
386
387 VirtualPathId::new(self.num_virtual_paths() - 1)
388 }
389
390 pub fn get_span_for_filename(&self, filename: &str) -> Option<Span> {
391 let predicate = |file: &CachedFile| &*file.name == filename;
392 let file_id = self
394 .delta
395 .files
396 .iter()
397 .rposition(predicate)
398 .map(|idx| idx + self.permanent_state.num_files())
399 .or_else(|| self.permanent_state.files().rposition(predicate))?;
400 let file_id = FileId::new(file_id);
401
402 Some(self.get_span_for_file(file_id))
403 }
404
405 pub fn get_span_for_file(&self, file_id: FileId) -> Span {
410 let result = self
411 .files()
412 .nth(file_id.get())
413 .expect("internal error: could not find source for previously parsed file");
414
415 result.covered_span
416 }
417
418 #[inline]
419 pub fn get_span_contents(&self, span: Span) -> &[u8] {
420 let permanent_end = self.permanent_state.next_span_start();
421 if permanent_end <= span.start {
422 for cached_file in &self.delta.files {
423 if cached_file.covered_span.contains_span(span) {
424 return &cached_file.content[span.start - cached_file.covered_span.start
425 ..span.end - cached_file.covered_span.start];
426 }
427 }
428 }
429
430 self.permanent_state.get_span_contents(span)
432 }
433
434 pub fn enter_scope(&mut self) {
435 self.delta.enter_scope();
436 }
437
438 pub fn exit_scope(&mut self) {
439 self.delta.exit_scope();
440 }
441
442 pub fn find_predecl(&self, name: &[u8]) -> Option<DeclId> {
444 let mut removed_overlays = vec![];
445
446 for scope_frame in self.delta.scope.iter().rev() {
447 if let Some(decl_id) = scope_frame.predecls.get(name) {
448 return Some(*decl_id);
449 }
450
451 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() {
452 if let Some(decl_id) = overlay_frame.predecls.get(name) {
453 return Some(*decl_id);
454 }
455 }
456 }
457
458 None
459 }
460
461 pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
467 let mut removed_overlays = vec![];
468
469 let mut visibility = VisibilityStack::default();
470
471 for scope_frame in self.delta.scope.iter().rev() {
472 if self.search_predecls
473 && let Some(decl_id) = scope_frame.predecls.get(name)
474 && visibility.is_decl_id_visible(decl_id)
475 {
476 return Some(*decl_id);
477 }
478
479 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() {
481 visibility.push(&overlay_frame.visibility);
482
483 if self.search_predecls
484 && let Some(decl_id) = overlay_frame.predecls.get(name)
485 && visibility.is_decl_id_visible(decl_id)
486 {
487 return Some(*decl_id);
488 }
489
490 if let Some(decl_id) = overlay_frame.get_decl(name)
491 && visibility.is_decl_id_visible(&decl_id)
492 {
493 return Some(decl_id);
494 }
495 }
496 }
497
498 self.permanent_state.find_decl(name, &removed_overlays)
500 }
501
502 pub fn find_decl_name(&self, decl_id: DeclId) -> Option<&[u8]> {
507 let mut removed_overlays = vec![];
508
509 let mut visibility = VisibilityStack::default();
510
511 for scope_frame in self.delta.scope.iter().rev() {
512 if self.search_predecls {
513 for (name, id) in scope_frame.predecls.iter() {
514 if id == &decl_id {
515 return Some(name);
516 }
517 }
518 }
519
520 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() {
522 visibility.push(&overlay_frame.visibility);
523
524 if self.search_predecls {
525 for (name, id) in overlay_frame.predecls.iter() {
526 if id == &decl_id {
527 return Some(name);
528 }
529 }
530 }
531
532 if visibility.is_decl_id_visible(&decl_id) {
533 for (name, id) in overlay_frame.decls.iter() {
534 if id == &decl_id {
535 return Some(name);
536 }
537 }
538 }
539 }
540 }
541
542 self.permanent_state
544 .find_decl_name(decl_id, &removed_overlays)
545 }
546
547 pub fn find_module(&self, name: &[u8]) -> Option<ModuleId> {
552 let mut removed_overlays = vec![];
553
554 for scope_frame in self.delta.scope.iter().rev() {
555 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() {
556 if let Some(module_id) = overlay_frame.modules.get(name) {
557 return Some(*module_id);
558 }
559 }
560 }
561
562 for overlay_frame in self
563 .permanent_state
564 .active_overlays(&removed_overlays)
565 .rev()
566 {
567 if let Some(module_id) = overlay_frame.modules.get(name) {
568 return Some(*module_id);
569 }
570 }
571
572 None
573 }
574
575 pub fn next_var_id(&self) -> VarId {
576 let num_permanent_vars = self.permanent_state.num_vars();
577 VarId::new(num_permanent_vars + self.delta.vars.len())
578 }
579
580 pub fn list_variables(&self) -> Vec<&[u8]> {
581 let mut removed_overlays = vec![];
582 let mut variables = HashSet::new();
583 for scope_frame in self.delta.scope.iter() {
584 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays) {
585 variables.extend(overlay_frame.vars.keys().map(|k| &k[..]));
586 }
587 }
588
589 let permanent_vars = self
590 .permanent_state
591 .active_overlays(&removed_overlays)
592 .flat_map(|overlay_frame| overlay_frame.vars.keys().map(|k| &k[..]));
593
594 variables.extend(permanent_vars);
595 variables.into_iter().collect()
596 }
597
598 pub fn find_variable(&self, name: &[u8]) -> Option<VarId> {
599 let mut name = name.to_vec();
600 if !name.starts_with(b"$") {
601 name.insert(0, b'$');
602 }
603 let mut removed_overlays = vec![];
604
605 for scope_frame in self.delta.scope.iter().rev() {
606 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() {
607 if let Some(var_id) = overlay_frame.vars.get(&name) {
608 return Some(*var_id);
609 }
610 }
611 }
612
613 for overlay_frame in self
614 .permanent_state
615 .active_overlays(&removed_overlays)
616 .rev()
617 {
618 if let Some(var_id) = overlay_frame.vars.get(&name) {
619 return Some(*var_id);
620 }
621 }
622
623 None
624 }
625
626 pub fn find_variable_in_current_frame(&self, name: &[u8]) -> Option<VarId> {
627 let mut removed_overlays = vec![];
628
629 for scope_frame in self.delta.scope.iter().rev().take(1) {
630 for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() {
631 if let Some(var_id) = overlay_frame.vars.get(name) {
632 return Some(*var_id);
633 }
634 }
635 }
636
637 None
638 }
639
640 pub fn add_variable(&mut self, name: Vec<u8>, span: Span, ty: Type, mutable: bool) -> VarId {
641 let var_id = self.add_variable_without_scope(span, ty, mutable);
642 self.insert_variable_into_scope(name, var_id);
643 var_id
644 }
645
646 pub fn add_variable_without_scope(&mut self, span: Span, ty: Type, mutable: bool) -> VarId {
651 let next_id = self.next_var_id();
652 self.delta.vars.push(Variable::new(span, ty, mutable));
653 next_id
654 }
655
656 pub fn insert_variable_into_scope(&mut self, mut name: Vec<u8>, var_id: VarId) {
659 if !name.starts_with(b"$") {
660 name.insert(0, b'$');
661 }
662 if let Some(var) = self.get_variable_mut(var_id) {
666 var.name = Some(name.clone());
667 }
668 self.last_overlay_mut().insert_variable(name, var_id);
669 }
670
671 #[deprecated(since = "0.92.3", note = "please use `EngineState::cwd()` instead")]
676 pub fn get_cwd(&self) -> String {
677 self.permanent_state
678 .cwd(None)
679 .map(|path| path.to_string_lossy().to_string())
680 .unwrap_or_default()
681 }
682
683 pub fn get_env_var(&self, name: &str) -> Option<&Value> {
684 self.permanent_state.get_env_var(name)
685 }
686
687 pub fn get_config(&self) -> &Arc<Config> {
692 &self.permanent_state.config
693 }
694
695 pub fn set_variable_type(&mut self, var_id: VarId, ty: Type) {
696 let num_permanent_vars = self.permanent_state.num_vars();
697 if var_id.get() < num_permanent_vars {
698 panic!("Internal error: attempted to set into permanent state from working set")
699 } else {
700 self.delta.vars[var_id.get() - num_permanent_vars].ty = ty;
701 }
702 }
703
704 pub fn set_variable_const_val(&mut self, var_id: VarId, val: Value) {
705 let num_permanent_vars = self.permanent_state.num_vars();
706 if var_id.get() < num_permanent_vars {
707 panic!("Internal error: attempted to set into permanent state from working set")
708 } else {
709 self.delta.vars[var_id.get() - num_permanent_vars].const_val = Some(val);
710 }
711 }
712
713 pub fn get_variable(&self, var_id: VarId) -> &Variable {
714 let num_permanent_vars = self.permanent_state.num_vars();
715 if var_id.get() < num_permanent_vars {
716 self.permanent_state.get_var(var_id)
717 } else {
718 self.delta
719 .vars
720 .get(var_id.get() - num_permanent_vars)
721 .expect("internal error: missing variable")
722 }
723 }
724
725 pub fn get_variable_mut(&mut self, var_id: VarId) -> Option<&mut Variable> {
729 let num_permanent_vars = self.permanent_state.num_vars();
730 if var_id.get() < num_permanent_vars {
731 None
732 } else {
733 self.delta.vars.get_mut(var_id.get() - num_permanent_vars)
734 }
735 }
736
737 pub fn get_variable_if_possible(&self, var_id: VarId) -> Option<&Variable> {
738 let num_permanent_vars = self.permanent_state.num_vars();
739 if var_id.get() < num_permanent_vars {
740 Some(self.permanent_state.get_var(var_id))
741 } else {
742 self.delta.vars.get(var_id.get() - num_permanent_vars)
743 }
744 }
745
746 pub fn snapshot_scope_bindings(&self) -> Option<Arc<ScopeBindings>> {
755 let frame = self.delta.last_scope_frame();
756 let mut bindings = ScopeBindings::default();
757 let mut removed_overlays = vec![];
758
759 for overlay in frame.active_overlays(&mut removed_overlays) {
760 bindings.extend_from_overlay(overlay);
761 }
762
763 if bindings.is_empty() {
764 None
765 } else {
766 Some(Arc::new(bindings))
767 }
768 }
769
770 pub fn get_constant(&self, var_id: VarId) -> Result<&Value, ParseError> {
771 let var = self.get_variable(var_id);
772
773 if let Some(const_val) = &var.const_val {
774 Ok(const_val)
775 } else {
776 Err(ParseError::InternalError(
777 "constant does not have a constant value".into(),
778 var.declaration_span,
779 ))
780 }
781 }
782
783 pub fn get_decl(&self, decl_id: DeclId) -> &dyn Command {
784 let num_permanent_decls = self.permanent_state.num_decls();
785 if decl_id.get() < num_permanent_decls {
786 self.permanent_state.get_decl(decl_id)
787 } else {
788 self.delta
789 .decls
790 .get(decl_id.get() - num_permanent_decls)
791 .expect("internal error: missing declaration")
792 .as_ref()
793 }
794 }
795
796 pub fn get_decl_mut(&mut self, decl_id: DeclId) -> &mut Box<dyn Command> {
797 let num_permanent_decls = self.permanent_state.num_decls();
798 if decl_id.get() < num_permanent_decls {
799 panic!("internal error: can only mutate declarations in working set")
800 } else {
801 self.delta
802 .decls
803 .get_mut(decl_id.get() - num_permanent_decls)
804 .expect("internal error: missing declaration")
805 }
806 }
807
808 pub fn get_signature(&self, decl: &dyn Command) -> Signature {
809 if let Some(block_id) = decl.block_id() {
810 *self.get_block(block_id).signature.clone()
811 } else {
812 decl.signature()
813 }
814 }
815
816 pub fn get_signature_shared(&self, decl_id: DeclId) -> Arc<Signature> {
821 if decl_id.get() >= self.permanent_state.num_decls() {
822 return Arc::new(self.get_signature(self.get_decl(decl_id)));
823 }
824 let mut cache = self
825 .permanent_signatures
826 .lock()
827 .unwrap_or_else(|poisoned| poisoned.into_inner());
828 Arc::clone(
829 cache
830 .entry(decl_id)
831 .or_insert_with(|| Arc::new(self.get_signature(self.get_decl(decl_id)))),
832 )
833 }
834
835 pub fn get_decl_signature_shared(&self, decl_id: DeclId) -> Arc<Signature> {
840 if decl_id.get() >= self.permanent_state.num_decls() {
841 return Arc::new(self.get_decl(decl_id).signature());
842 }
843 let mut cache = self
844 .permanent_decl_signatures
845 .lock()
846 .unwrap_or_else(|poisoned| poisoned.into_inner());
847 Arc::clone(
848 cache
849 .entry(decl_id)
850 .or_insert_with(|| Arc::new(self.get_decl(decl_id).signature())),
851 )
852 }
853
854 pub fn traverse_commands(&self, mut f: impl FnMut(&[u8], DeclId)) {
856 for scope_frame in self.delta.scope.iter().rev() {
857 for overlay_id in scope_frame.active_overlays.iter().rev() {
858 let overlay_frame = scope_frame.get_overlay(*overlay_id);
859
860 for (name, decl_id) in &overlay_frame.decls {
861 if overlay_frame.visibility.is_decl_id_visible(decl_id) {
862 f(name, *decl_id);
863 }
864 }
865 }
866 }
867
868 self.permanent_state.traverse_commands(f);
869 }
870
871 pub fn find_commands_by_predicate(
872 &self,
873 mut predicate: impl FnMut(&[u8]) -> bool,
874 ignore_deprecated: bool,
875 ) -> Vec<(DeclId, Vec<u8>, Option<String>, CommandType)> {
876 let mut output = vec![];
877
878 self.traverse_commands(|name, decl_id| {
879 if !predicate(name) {
880 return;
881 }
882 let command = self.get_decl(decl_id);
883 if ignore_deprecated && command.signature().category == Category::Removed {
884 return;
885 }
886 output.push((
887 decl_id,
888 name.to_vec(),
889 Some(command.description().to_string()),
890 command.command_type(),
891 ));
892 });
893
894 output
895 }
896
897 pub fn get_block(&self, block_id: BlockId) -> &Arc<Block> {
898 let num_permanent_blocks = self.permanent_state.num_blocks();
899 if block_id.get() < num_permanent_blocks {
900 self.permanent_state.get_block(block_id)
901 } else {
902 self.delta
903 .blocks
904 .get(block_id.get() - num_permanent_blocks)
905 .expect("internal error: missing block")
906 }
907 }
908
909 pub fn get_module(&self, module_id: ModuleId) -> &Module {
910 let num_permanent_modules = self.permanent_state.num_modules();
911 if module_id.get() < num_permanent_modules {
912 self.permanent_state.get_module(module_id)
913 } else {
914 self.delta
915 .modules
916 .get(module_id.get() - num_permanent_modules)
917 .expect("internal error: missing module")
918 }
919 }
920
921 pub fn get_block_mut(&mut self, block_id: BlockId) -> &mut Block {
922 let num_permanent_blocks = self.permanent_state.num_blocks();
923 if block_id.get() < num_permanent_blocks {
924 panic!("Attempt to mutate a block that is in the permanent (immutable) state")
925 } else {
926 self.delta
927 .blocks
928 .get_mut(block_id.get() - num_permanent_blocks)
929 .map(Arc::make_mut)
930 .expect("internal error: missing block")
931 }
932 }
933
934 pub fn find_overlay(&self, name: &[u8]) -> Option<&OverlayFrame> {
936 for scope_frame in self.delta.scope.iter().rev() {
937 if let Some(overlay_id) = scope_frame.find_overlay(name) {
938 return Some(scope_frame.get_overlay(overlay_id));
939 }
940 }
941
942 self.permanent_state
943 .find_overlay(name)
944 .map(|id| self.permanent_state.get_overlay(id))
945 }
946
947 pub fn last_overlay_name(&self) -> &[u8] {
948 let mut removed_overlays = vec![];
949
950 for scope_frame in self.delta.scope.iter().rev() {
951 if let Some(last_name) = scope_frame
952 .active_overlay_names(&mut removed_overlays)
953 .iter()
954 .rev()
955 .next_back()
956 {
957 return last_name;
958 }
959 }
960
961 self.permanent_state.last_overlay_name(&removed_overlays)
962 }
963
964 pub fn last_overlay(&self) -> &OverlayFrame {
965 let mut removed_overlays = vec![];
966
967 for scope_frame in self.delta.scope.iter().rev() {
968 if let Some(last_overlay) = scope_frame
969 .active_overlays(&mut removed_overlays)
970 .rev()
971 .next_back()
972 {
973 return last_overlay;
974 }
975 }
976
977 self.permanent_state.last_overlay(&removed_overlays)
978 }
979
980 pub fn last_overlay_mut(&mut self) -> &mut OverlayFrame {
981 if self.delta.last_overlay_mut().is_none() {
982 let overlay_frame = self.last_overlay();
984 let name = self.last_overlay_name().to_vec();
985 let origin = overlay_frame.origin;
986 let prefixed = overlay_frame.prefixed;
987 self.add_overlay(
988 name,
989 origin,
990 ResolvedImportPattern::new(vec![], vec![], vec![], vec![]),
991 prefixed,
992 );
993 }
994
995 self.delta
996 .last_overlay_mut()
997 .expect("internal error: missing added overlay")
998 }
999
1000 pub fn decls_of_overlay(&self, name: &[u8]) -> HashMap<Vec<u8>, DeclId> {
1002 let mut result = HashMap::new();
1003
1004 if let Some(overlay_id) = self.permanent_state.find_overlay(name) {
1005 let overlay_frame = self.permanent_state.get_overlay(overlay_id);
1006
1007 for (decl_key, decl_id) in &overlay_frame.decls {
1008 result.insert(decl_key.to_owned(), *decl_id);
1009 }
1010 }
1011
1012 for scope_frame in self.delta.scope.iter() {
1013 if let Some(overlay_id) = scope_frame.find_overlay(name) {
1014 let overlay_frame = scope_frame.get_overlay(overlay_id);
1015
1016 for (decl_key, decl_id) in &overlay_frame.decls {
1017 result.insert(decl_key.to_owned(), *decl_id);
1018 }
1019 }
1020 }
1021
1022 result
1023 }
1024
1025 pub fn add_overlay(
1026 &mut self,
1027 name: Vec<u8>,
1028 origin: ModuleId,
1029 definitions: ResolvedImportPattern,
1030 prefixed: bool,
1031 ) {
1032 let last_scope_frame = self.delta.last_scope_frame_mut();
1033
1034 last_scope_frame
1035 .removed_overlays
1036 .retain(|removed_name| removed_name != &name);
1037
1038 let overlay_id = if let Some(overlay_id) = last_scope_frame.find_overlay(&name) {
1039 last_scope_frame.get_overlay_mut(overlay_id).origin = origin;
1040
1041 overlay_id
1042 } else {
1043 last_scope_frame
1044 .overlays
1045 .push((name, OverlayFrame::from_origin(origin, prefixed)));
1046 OverlayId::new(last_scope_frame.overlays.len() - 1)
1047 };
1048
1049 last_scope_frame
1050 .active_overlays
1051 .retain(|id| id != &overlay_id);
1052 last_scope_frame.active_overlays.push(overlay_id);
1053
1054 self.use_decls(definitions.decls);
1055 self.use_modules(definitions.modules);
1056
1057 let mut constants = vec![];
1058
1059 for (name, const_vid) in definitions.constants {
1060 constants.push((name, const_vid));
1061 }
1062
1063 for (name, const_val) in definitions.constant_values {
1064 let const_var_id =
1065 self.add_variable(name.clone(), Span::unknown(), const_val.get_type(), false);
1066 self.set_variable_const_val(const_var_id, const_val);
1067 constants.push((name, const_var_id));
1068 }
1069 self.use_variables(constants);
1070 }
1071
1072 pub fn remove_overlay(&mut self, name: &[u8], keep_custom: bool) {
1073 let last_scope_frame = self.delta.last_scope_frame_mut();
1074
1075 let maybe_module_id = if let Some(overlay_id) = last_scope_frame.find_overlay(name) {
1076 last_scope_frame
1077 .active_overlays
1078 .retain(|id| id != &overlay_id);
1079
1080 Some(last_scope_frame.get_overlay(overlay_id).origin)
1081 } else {
1082 self.permanent_state
1083 .find_overlay(name)
1084 .map(|id| self.permanent_state.get_overlay(id).origin)
1085 };
1086
1087 if let Some(module_id) = maybe_module_id {
1088 last_scope_frame.removed_overlays.push(name.to_owned());
1089
1090 if keep_custom {
1091 let origin_module = self.get_module(module_id);
1092
1093 let decls = self
1094 .decls_of_overlay(name)
1095 .into_iter()
1096 .filter(|(n, _)| !origin_module.has_decl(n))
1097 .collect();
1098
1099 self.use_decls(decls);
1100 }
1101 }
1102 }
1103
1104 pub fn render(self) -> StateDelta {
1105 self.delta
1106 }
1107
1108 pub fn build_desc(&self, spans: &[Span]) -> (String, String) {
1109 let comment_lines: Vec<&[u8]> = spans
1110 .iter()
1111 .map(|span| self.get_span_contents(*span))
1112 .collect();
1113 build_desc(&comment_lines)
1114 }
1115
1116 pub fn find_block_by_span(&self, span: Span) -> Option<Arc<Block>> {
1117 for block in &self.delta.blocks {
1118 if Some(span) == block.span {
1119 return Some(block.clone());
1120 }
1121 }
1122
1123 for block in self.permanent_state.blocks.iter() {
1124 if Some(span) == block.span {
1125 return Some(block.clone());
1126 }
1127 }
1128
1129 None
1130 }
1131
1132 pub fn blocks_with_span_newest_first(&self, span: Span) -> Vec<Arc<Block>> {
1134 let mut blocks = Vec::new();
1135 for block in self.delta.blocks.iter().rev() {
1136 if block.span == Some(span) {
1137 blocks.push(block.clone());
1138 }
1139 }
1140 for block in self.permanent_state.blocks.iter().rev() {
1141 if block.span == Some(span) {
1142 blocks.push(block.clone());
1143 }
1144 }
1145 blocks
1146 }
1147
1148 pub fn find_block_id_of(&self, block: &Arc<Block>) -> Option<BlockId> {
1150 for (idx, existing) in self.delta.blocks.iter().enumerate() {
1151 if Arc::ptr_eq(existing, block) {
1152 return Some(BlockId::new(self.permanent_state.num_blocks() + idx));
1153 }
1154 }
1155 for (idx, existing) in self.permanent_state.blocks.iter().enumerate() {
1156 if Arc::ptr_eq(existing, block) {
1157 return Some(BlockId::new(idx));
1158 }
1159 }
1160 None
1161 }
1162
1163 pub fn find_module_by_span(&self, span: Span) -> Option<ModuleId> {
1164 for (id, module) in self.delta.modules.iter().enumerate() {
1165 if Some(span) == module.span {
1166 return Some(ModuleId::new(self.permanent_state.num_modules() + id));
1167 }
1168 }
1169
1170 for (module_id, module) in self.permanent_state.modules.iter().enumerate() {
1171 if Some(span) == module.span {
1172 return Some(ModuleId::new(module_id));
1173 }
1174 }
1175
1176 None
1177 }
1178
1179 pub fn find_file_by_span(&self, span: Span) -> Option<&CachedFile> {
1181 self.files()
1182 .rev()
1184 .find(|file| file.covered_span.contains_span(span))
1185 }
1186
1187 pub fn find_virtual_path(&self, name: &str) -> Option<&VirtualPath> {
1188 let virtual_path_name = Path::new(name);
1190
1191 for (virtual_name, virtual_path) in self.delta.virtual_paths.iter().rev() {
1192 if Path::new(virtual_name) == virtual_path_name {
1193 return Some(virtual_path);
1194 }
1195 }
1196
1197 for (virtual_name, virtual_path) in self.permanent_state.virtual_paths.iter().rev() {
1198 if Path::new(virtual_name) == virtual_path_name {
1199 return Some(virtual_path);
1200 }
1201 }
1202
1203 None
1204 }
1205
1206 pub fn get_virtual_path(&self, virtual_path_id: VirtualPathId) -> &(String, VirtualPath) {
1207 let num_permanent_virtual_paths = self.permanent_state.num_virtual_paths();
1208 if virtual_path_id.get() < num_permanent_virtual_paths {
1209 self.permanent_state.get_virtual_path(virtual_path_id)
1210 } else {
1211 self.delta
1212 .virtual_paths
1213 .get(virtual_path_id.get() - num_permanent_virtual_paths)
1214 .expect("internal error: missing virtual path")
1215 }
1216 }
1217
1218 pub fn add_span(&mut self, span: Span) -> SpanId {
1219 let num_permanent_spans = self.permanent_state.spans.len();
1220 self.delta.spans.push(span);
1221 SpanId::new(num_permanent_spans + self.delta.spans.len() - 1)
1222 }
1223
1224 pub fn resolve_span<'s>(&'s self, span: Span) -> Option<ResolvedSpan<'s>> {
1225 let cached_file = self.find_file_by_span(span)?;
1226 let file = cached_file.name.as_ref().into();
1227 let span = span.offset(cached_file.covered_span.start);
1228 Some(ResolvedSpan { file, span })
1229 }
1230}
1231
1232impl<'a> GetSpan for &'a StateWorkingSet<'a> {
1233 fn get_span(&self, span_id: SpanId) -> Span {
1234 let num_permanent_spans = self.permanent_state.num_spans();
1235 if span_id.get() < num_permanent_spans {
1236 self.permanent_state.get_span(span_id)
1237 } else {
1238 *self
1239 .delta
1240 .spans
1241 .get(span_id.get() - num_permanent_spans)
1242 .expect("internal error: missing span")
1243 }
1244 }
1245}
1246
1247impl miette::SourceCode for &StateWorkingSet<'_> {
1248 fn read_span<'b>(
1249 &'b self,
1250 span: &miette::SourceSpan,
1251 context_lines_before: usize,
1252 context_lines_after: usize,
1253 ) -> Result<Box<dyn miette::SpanContents<'b> + 'b>, miette::MietteError> {
1254 let debugging = std::env::var("MIETTE_DEBUG").is_ok();
1255 if debugging {
1256 let finding_span = "Finding span in StateWorkingSet";
1257 dbg!(finding_span, span);
1258 }
1259 for cached_file in self.files() {
1260 let (filename, start, end) = (
1261 &cached_file.name,
1262 cached_file.covered_span.start,
1263 cached_file.covered_span.end,
1264 );
1265 if debugging {
1266 dbg!(&filename, start, end);
1267 }
1268 if span.offset() >= start && span.offset() + span.len() <= end {
1269 if debugging {
1270 let found_file = "Found matching file";
1271 dbg!(found_file);
1272 }
1273 let our_span = cached_file.covered_span;
1274 let local_span = (span.offset() - start, span.len()).into();
1277 if debugging {
1278 dbg!(&local_span);
1279 }
1280 let span_contents = self.get_span_contents(our_span);
1281 if debugging {
1282 dbg!(String::from_utf8_lossy(span_contents));
1283 }
1284 let span_contents = span_contents.read_span(
1285 &local_span,
1286 context_lines_before,
1287 context_lines_after,
1288 )?;
1289 let content_span = span_contents.span();
1290 let retranslated = (content_span.offset() + start, content_span.len()).into();
1292 if debugging {
1293 dbg!(&retranslated);
1294 }
1295
1296 let data = span_contents.data();
1297 if &**filename == "<cli>" {
1298 if debugging {
1299 let success_cli = "Successfully read CLI span";
1300 dbg!(success_cli, String::from_utf8_lossy(data));
1301 }
1302 return Ok(Box::new(miette::MietteSpanContents::new(
1303 data,
1304 retranslated,
1305 span_contents.line(),
1306 span_contents.column(),
1307 span_contents.line_count(),
1308 )));
1309 } else {
1310 if debugging {
1311 let success_file = "Successfully read file span";
1312 dbg!(success_file);
1313 }
1314 return Ok(Box::new(miette::MietteSpanContents::new_named(
1315 (**filename).to_owned(),
1316 data,
1317 retranslated,
1318 span_contents.line(),
1319 span_contents.column(),
1320 span_contents.line_count(),
1321 )));
1322 }
1323 }
1324 }
1325 Err(miette::MietteError::OutOfBounds)
1326 }
1327}
1328
1329#[derive(Debug, Default)]
1339pub struct FileStack(Vec<PathBuf>);
1340
1341impl FileStack {
1342 pub fn new() -> Self {
1344 Self(vec![])
1345 }
1346
1347 pub fn with_file(path: PathBuf) -> Self {
1352 Self(vec![path])
1353 }
1354
1355 pub fn push(&mut self, path: PathBuf, span: Span) -> Result<(), ParseError> {
1359 if let Some(i) = self.0.iter().rposition(|p| p == &path) {
1361 let filenames: Vec<String> = self.0[i..]
1362 .iter()
1363 .chain(std::iter::once(&path))
1364 .map(|p| p.to_string_lossy().to_string())
1365 .collect();
1366 let msg = filenames.join("\nuses ");
1367 return Err(ParseError::CircularImport(msg, span));
1368 }
1369
1370 self.0.push(path);
1371 Ok(())
1372 }
1373
1374 pub fn pop(&mut self) -> Option<PathBuf> {
1376 self.0.pop()
1377 }
1378
1379 pub fn top(&self) -> Option<&Path> {
1381 self.0.last().map(PathBuf::as_path)
1382 }
1383
1384 pub fn current_working_directory(&self) -> Option<&Path> {
1387 self.0.last().and_then(|path| path.parent())
1388 }
1389}