1use std::convert::TryFrom;
37use std::fmt::Display;
38use std::num::NonZeroU32;
39
40use controlled_option::ControlledOption;
41use controlled_option::Niche;
42use enumset::EnumSetType;
43use smallvec::SmallVec;
44
45use crate::arena::Deque;
46use crate::arena::DequeArena;
47use crate::arena::Handle;
48use crate::graph::Edge;
49use crate::graph::Node;
50use crate::graph::NodeID;
51use crate::graph::StackGraph;
52use crate::graph::Symbol;
53use crate::paths::PathResolutionError;
54use crate::utils::cmp_option;
55use crate::utils::equals_option;
56
57trait DisplayWithPartialPaths {
83 fn prepare(&mut self, _graph: &StackGraph, _partials: &mut PartialPaths) {}
84
85 fn display_with(
86 &self,
87 graph: &StackGraph,
88 partials: &PartialPaths,
89 f: &mut std::fmt::Formatter,
90 ) -> std::fmt::Result;
91}
92
93fn display_with<'a, D>(
98 mut value: D,
99 graph: &'a StackGraph,
100 partials: &'a mut PartialPaths,
101) -> impl Display + 'a
102where
103 D: DisplayWithPartialPaths + 'a,
104{
105 value.prepare(graph, partials);
106 DisplayWithPartialPathsWrapper {
107 value,
108 graph,
109 partials,
110 }
111}
112
113fn display_prepared<'a, D>(
117 value: D,
118 graph: &'a StackGraph,
119 partials: &'a PartialPaths,
120) -> impl Display + 'a
121where
122 D: DisplayWithPartialPaths + 'a,
123{
124 DisplayWithPartialPathsWrapper {
125 value,
126 graph,
127 partials,
128 }
129}
130
131#[doc(hidden)]
132struct DisplayWithPartialPathsWrapper<'a, D> {
133 value: D,
134 graph: &'a StackGraph,
135 partials: &'a PartialPaths,
136}
137
138impl<'a, D> Display for DisplayWithPartialPathsWrapper<'a, D>
139where
140 D: DisplayWithPartialPaths,
141{
142 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
143 self.value.display_with(self.graph, self.partials, f)
144 }
145}
146
147#[repr(transparent)]
152#[derive(Clone, Copy, Debug, Eq, Hash, Niche, Ord, PartialEq, PartialOrd)]
153pub struct SymbolStackVariable(#[niche] NonZeroU32);
154
155impl SymbolStackVariable {
156 pub fn new(variable: u32) -> Option<SymbolStackVariable> {
157 NonZeroU32::new(variable).map(SymbolStackVariable)
158 }
159
160 pub(crate) fn initial() -> SymbolStackVariable {
163 SymbolStackVariable(unsafe { NonZeroU32::new_unchecked(1) })
164 }
165
166 pub fn with_offset(self, symbol_variable_offset: u32) -> SymbolStackVariable {
173 let offset_value = self.0.get() + symbol_variable_offset;
174 SymbolStackVariable(unsafe { NonZeroU32::new_unchecked(offset_value) })
175 }
176
177 pub(crate) fn as_u32(self) -> u32 {
178 self.0.get()
179 }
180
181 fn as_usize(self) -> usize {
182 self.0.get() as usize
183 }
184}
185
186impl Display for SymbolStackVariable {
187 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
188 write!(f, "%{}", self.0.get())
189 }
190}
191
192impl From<NonZeroU32> for SymbolStackVariable {
193 fn from(value: NonZeroU32) -> SymbolStackVariable {
194 SymbolStackVariable(value)
195 }
196}
197
198impl Into<u32> for SymbolStackVariable {
199 fn into(self) -> u32 {
200 self.0.get()
201 }
202}
203
204impl TryFrom<u32> for SymbolStackVariable {
205 type Error = ();
206 fn try_from(value: u32) -> Result<SymbolStackVariable, ()> {
207 let value = NonZeroU32::new(value).ok_or(())?;
208 Ok(SymbolStackVariable(value))
209 }
210}
211
212#[repr(transparent)]
217#[derive(Clone, Copy, Debug, Eq, Hash, Niche, Ord, PartialEq, PartialOrd)]
218pub struct ScopeStackVariable(#[niche] NonZeroU32);
219
220impl ScopeStackVariable {
221 pub fn new(variable: u32) -> Option<ScopeStackVariable> {
222 NonZeroU32::new(variable).map(ScopeStackVariable)
223 }
224
225 fn initial() -> ScopeStackVariable {
228 ScopeStackVariable(unsafe { NonZeroU32::new_unchecked(1) })
229 }
230
231 fn fresher_than(max_used: u32) -> ScopeStackVariable {
234 ScopeStackVariable(unsafe { NonZeroU32::new_unchecked(max_used + 1) })
235 }
236
237 pub fn with_offset(self, scope_variable_offset: u32) -> ScopeStackVariable {
244 let offset_value = self.0.get() + scope_variable_offset;
245 ScopeStackVariable(unsafe { NonZeroU32::new_unchecked(offset_value) })
246 }
247
248 pub(crate) fn as_u32(self) -> u32 {
249 self.0.get()
250 }
251
252 fn as_usize(self) -> usize {
253 self.0.get() as usize
254 }
255}
256
257impl Display for ScopeStackVariable {
258 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
259 write!(f, "${}", self.0.get())
260 }
261}
262
263impl From<NonZeroU32> for ScopeStackVariable {
264 fn from(value: NonZeroU32) -> ScopeStackVariable {
265 ScopeStackVariable(value)
266 }
267}
268
269impl Into<u32> for ScopeStackVariable {
270 fn into(self) -> u32 {
271 self.0.get()
272 }
273}
274
275impl TryFrom<u32> for ScopeStackVariable {
276 type Error = ();
277 fn try_from(value: u32) -> Result<ScopeStackVariable, ()> {
278 let value = NonZeroU32::new(value).ok_or(())?;
279 Ok(ScopeStackVariable(value))
280 }
281}
282
283#[repr(C)]
288#[derive(Clone, Copy)]
289pub struct PartialScopedSymbol {
290 pub symbol: Handle<Symbol>,
291 pub scopes: ControlledOption<PartialScopeStack>,
294}
295
296impl PartialScopedSymbol {
297 pub fn with_offset(mut self, scope_variable_offset: u32) -> PartialScopedSymbol {
304 let scopes = self
305 .scopes
306 .into_option()
307 .map(|stack| stack.with_offset(scope_variable_offset));
308 self.scopes = ControlledOption::from_option(scopes);
309 self
310 }
311
312 pub fn unify(
315 &mut self,
316 partials: &mut PartialPaths,
317 rhs: PartialScopedSymbol,
318 scope_bindings: &mut PartialScopeStackBindings,
319 ) -> Result<(), PathResolutionError> {
320 if self.symbol != rhs.symbol {
321 return Err(PathResolutionError::SymbolStackUnsatisfied);
322 }
323 match (self.scopes.into_option(), rhs.scopes.into_option()) {
324 (Some(lhs), Some(rhs)) => {
325 let unified = lhs.unify(partials, rhs, scope_bindings)?;
326 self.scopes = ControlledOption::some(unified);
327 }
328 (None, None) => {}
329 _ => return Err(PathResolutionError::SymbolStackUnsatisfied),
330 }
331 Ok(())
332 }
333
334 pub fn matches(self, partials: &mut PartialPaths, postcondition: PartialScopedSymbol) -> bool {
337 if self.symbol != postcondition.symbol {
338 return false;
339 }
340
341 if self.scopes.is_none() != postcondition.scopes.is_none() {
344 return false;
345 }
346
347 if let Some(precondition_scopes) = self.scopes.into_option() {
349 if let Some(postcondition_scopes) = postcondition.scopes.into_option() {
350 return precondition_scopes.matches(partials, postcondition_scopes);
351 }
352 }
353
354 true
355 }
356
357 pub fn apply_partial_bindings(
359 mut self,
360 partials: &mut PartialPaths,
361 scope_bindings: &PartialScopeStackBindings,
362 ) -> Result<PartialScopedSymbol, PathResolutionError> {
363 let scopes = match self.scopes.into_option() {
364 Some(scopes) => Some(scopes.apply_partial_bindings(partials, scope_bindings)?),
365 None => None,
366 };
367 self.scopes = scopes.into();
368 Ok(self)
369 }
370
371 pub fn equals(&self, partials: &mut PartialPaths, other: &PartialScopedSymbol) -> bool {
372 self.symbol == other.symbol
373 && equals_option(
374 self.scopes.into_option(),
375 other.scopes.into_option(),
376 |a, b| a.equals(partials, b),
377 )
378 }
379
380 pub fn cmp(
381 &self,
382 graph: &StackGraph,
383 partials: &mut PartialPaths,
384 other: &PartialScopedSymbol,
385 ) -> std::cmp::Ordering {
386 std::cmp::Ordering::Equal
387 .then_with(|| graph[self.symbol].cmp(&graph[other.symbol]))
388 .then_with(|| {
389 cmp_option(
390 self.scopes.into_option(),
391 other.scopes.into_option(),
392 |a, b| a.cmp(partials, b),
393 )
394 })
395 }
396
397 pub fn display<'a>(
398 self,
399 graph: &'a StackGraph,
400 partials: &'a mut PartialPaths,
401 ) -> impl Display + 'a {
402 display_with(self, graph, partials)
403 }
404}
405
406impl DisplayWithPartialPaths for PartialScopedSymbol {
407 fn prepare(&mut self, graph: &StackGraph, partials: &mut PartialPaths) {
408 if let Some(mut scopes) = self.scopes.into_option() {
409 scopes.prepare(graph, partials);
410 self.scopes = scopes.into();
411 }
412 }
413
414 fn display_with(
415 &self,
416 graph: &StackGraph,
417 partials: &PartialPaths,
418 f: &mut std::fmt::Formatter,
419 ) -> std::fmt::Result {
420 if let Some(scopes) = self.scopes.into_option() {
421 write!(
422 f,
423 "{}/({})",
424 self.symbol.display(graph),
425 display_prepared(scopes, graph, partials)
426 )
427 } else {
428 write!(f, "{}", self.symbol.display(graph))
429 }
430 }
431}
432
433#[repr(C)]
436#[derive(Clone, Copy, Niche)]
437pub struct PartialSymbolStack {
438 #[niche]
439 symbols: Deque<PartialScopedSymbol>,
440 length: u32,
441 variable: ControlledOption<SymbolStackVariable>,
442}
443
444impl PartialSymbolStack {
445 #[inline(always)]
447 pub fn can_match_empty(&self) -> bool {
448 self.symbols.is_empty()
449 }
450
451 #[inline(always)]
453 pub fn can_only_match_empty(&self) -> bool {
454 self.symbols.is_empty() && self.variable.is_none()
455 }
456
457 #[inline(always)]
459 pub fn contains_symbols(&self) -> bool {
460 !self.symbols.is_empty()
461 }
462
463 #[inline(always)]
465 pub fn has_variable(&self) -> bool {
466 self.variable.is_some()
467 }
468
469 #[inline(always)]
470 pub fn len(&self) -> usize {
471 self.length as usize
472 }
473
474 pub fn empty() -> PartialSymbolStack {
476 PartialSymbolStack {
477 symbols: Deque::empty(),
478 length: 0,
479 variable: ControlledOption::none(),
480 }
481 }
482
483 pub fn from_variable(variable: SymbolStackVariable) -> PartialSymbolStack {
485 PartialSymbolStack {
486 symbols: Deque::empty(),
487 length: 0,
488 variable: ControlledOption::some(variable),
489 }
490 }
491
492 pub fn have_reversal(&self, partials: &PartialPaths) -> bool {
495 self.symbols.have_reversal(&partials.partial_symbol_stacks)
496 }
497
498 pub fn with_offset(
505 mut self,
506 partials: &mut PartialPaths,
507 symbol_variable_offset: u32,
508 scope_variable_offset: u32,
509 ) -> PartialSymbolStack {
510 let mut result = match self.variable.into_option() {
511 Some(variable) => Self::from_variable(variable.with_offset(symbol_variable_offset)),
512 None => Self::empty(),
513 };
514 while let Some(symbol) = self.pop_front(partials) {
515 result.push_back(partials, symbol.with_offset(scope_variable_offset));
516 }
517 result
518 }
519
520 fn prepend(&mut self, partials: &mut PartialPaths, mut head: Deque<PartialScopedSymbol>) {
521 while let Some(head) = head.pop_back(&mut partials.partial_symbol_stacks).copied() {
522 self.push_front(partials, head);
523 }
524 }
525
526 pub fn push_front(&mut self, partials: &mut PartialPaths, symbol: PartialScopedSymbol) {
528 self.length += 1;
529 self.symbols
530 .push_front(&mut partials.partial_symbol_stacks, symbol);
531 }
532
533 pub fn push_back(&mut self, partials: &mut PartialPaths, symbol: PartialScopedSymbol) {
535 self.length += 1;
536 self.symbols
537 .push_back(&mut partials.partial_symbol_stacks, symbol);
538 }
539
540 pub fn pop_front(&mut self, partials: &mut PartialPaths) -> Option<PartialScopedSymbol> {
543 let result = self
544 .symbols
545 .pop_front(&mut partials.partial_symbol_stacks)
546 .copied();
547 if result.is_some() {
548 self.length -= 1;
549 }
550 result
551 }
552
553 pub fn pop_back(&mut self, partials: &mut PartialPaths) -> Option<PartialScopedSymbol> {
556 let result = self
557 .symbols
558 .pop_back(&mut partials.partial_symbol_stacks)
559 .copied();
560 if result.is_some() {
561 self.length -= 1;
562 }
563 result
564 }
565
566 pub fn display<'a>(
567 self,
568 graph: &'a StackGraph,
569 partials: &'a mut PartialPaths,
570 ) -> impl Display + 'a {
571 display_with(self, graph, partials)
572 }
573
574 pub fn matches(mut self, partials: &mut PartialPaths, mut other: PartialSymbolStack) -> bool {
577 while let Some(self_element) = self.pop_front(partials) {
578 if let Some(other_element) = other.pop_front(partials) {
579 if !self_element.matches(partials, other_element) {
580 return false;
581 }
582 } else {
583 return false;
585 }
586 }
587 if other.contains_symbols() {
588 return false;
590 }
591 self.variable.into_option() == other.variable.into_option()
592 }
593
594 pub fn apply_partial_bindings(
597 mut self,
598 partials: &mut PartialPaths,
599 symbol_bindings: &PartialSymbolStackBindings,
600 scope_bindings: &PartialScopeStackBindings,
601 ) -> Result<PartialSymbolStack, PathResolutionError> {
602 let mut result = match self.variable.into_option() {
605 Some(variable) => match symbol_bindings.get(variable) {
606 Some(bound) => bound,
607 None => PartialSymbolStack::from_variable(variable),
608 },
609 None => PartialSymbolStack::empty(),
610 };
611
612 while let Some(partial_symbol) = self.pop_back(partials) {
615 let partial_symbol = partial_symbol.apply_partial_bindings(partials, scope_bindings)?;
616 result.push_front(partials, partial_symbol);
617 }
618 Ok(result)
619 }
620
621 pub fn unify(
629 self,
630 partials: &mut PartialPaths,
631 mut rhs: PartialSymbolStack,
632 symbol_bindings: &mut PartialSymbolStackBindings,
633 scope_bindings: &mut PartialScopeStackBindings,
634 ) -> Result<PartialSymbolStack, PathResolutionError> {
635 let mut lhs = self;
636
637 let mut head = Deque::empty();
639 while lhs.contains_symbols() && rhs.contains_symbols() {
640 let mut lhs_front = lhs.pop_front(partials).unwrap();
641 let rhs_front = rhs.pop_front(partials).unwrap();
642 lhs_front.unify(partials, rhs_front, scope_bindings)?;
643 head.push_back(&mut partials.partial_symbol_stacks, lhs_front);
644 }
645
646 if !lhs.contains_symbols() && !rhs.contains_symbols() {
662 match (lhs.variable.into_option(), rhs.variable.into_option()) {
663 (None, None) => {
664 lhs.prepend(partials, head);
665 return Ok(lhs);
666 }
667 (None, Some(var)) => {
668 symbol_bindings.add(
669 partials,
670 var,
671 PartialSymbolStack::empty(),
672 scope_bindings,
673 )?;
674 rhs.prepend(partials, head);
675 return Ok(rhs);
676 }
677 (Some(var), None) => {
678 symbol_bindings.add(
679 partials,
680 var,
681 PartialSymbolStack::empty(),
682 scope_bindings,
683 )?;
684 lhs.prepend(partials, head);
685 return Ok(lhs);
686 }
687 (Some(lhs_var), Some(rhs_var)) => {
688 symbol_bindings.add(
689 partials,
690 rhs_var,
691 PartialSymbolStack::from_variable(lhs_var),
692 scope_bindings,
693 )?;
694 lhs.prepend(partials, head);
695 return Ok(lhs);
696 }
697 }
698 }
699
700 if !lhs.contains_symbols() && lhs.variable.is_none() {
712 return Err(PathResolutionError::SymbolStackUnsatisfied);
713 }
714 if !rhs.contains_symbols() && rhs.variable.is_none() {
715 return Err(PathResolutionError::SymbolStackUnsatisfied);
716 }
717
718 match (lhs.variable.into_option(), rhs.variable.into_option()) {
732 (Some(v1), Some(v2)) if v1 == v2 => {
733 return Err(PathResolutionError::ScopeStackUnsatisfied)
734 }
735 _ => {}
736 }
737 if lhs.contains_symbols() {
738 let rhs_variable = rhs.variable.into_option().unwrap();
739 symbol_bindings.add(partials, rhs_variable, lhs, scope_bindings)?;
740 lhs.prepend(partials, head);
741 return Ok(lhs);
742 }
743 if rhs.contains_symbols() {
744 let lhs_variable = lhs.variable.into_option().unwrap();
745 symbol_bindings.add(partials, lhs_variable, rhs, scope_bindings)?;
746 rhs.prepend(partials, head);
747 return Ok(rhs);
748 }
749
750 unreachable!();
751 }
752
753 pub fn equals(mut self, partials: &mut PartialPaths, mut other: PartialSymbolStack) -> bool {
754 while let Some(self_symbol) = self.pop_front(partials) {
755 if let Some(other_symbol) = other.pop_front(partials) {
756 if !self_symbol.equals(partials, &other_symbol) {
757 return false;
758 }
759 } else {
760 return false;
761 }
762 }
763 if !other.symbols.is_empty() {
764 return false;
765 }
766 equals_option(
767 self.variable.into_option(),
768 other.variable.into_option(),
769 |a, b| a == b,
770 )
771 }
772
773 pub fn cmp(
774 mut self,
775 graph: &StackGraph,
776 partials: &mut PartialPaths,
777 mut other: PartialSymbolStack,
778 ) -> std::cmp::Ordering {
779 use std::cmp::Ordering;
780 while let Some(self_symbol) = self.pop_front(partials) {
781 if let Some(other_symbol) = other.pop_front(partials) {
782 match self_symbol.cmp(graph, partials, &other_symbol) {
783 Ordering::Equal => continue,
784 result @ _ => return result,
785 }
786 } else {
787 return Ordering::Greater;
788 }
789 }
790 if !other.symbols.is_empty() {
791 return Ordering::Less;
792 }
793 cmp_option(
794 self.variable.into_option(),
795 other.variable.into_option(),
796 |a, b| a.cmp(&b),
797 )
798 }
799
800 pub fn iter<'a>(
802 &self,
803 partials: &'a mut PartialPaths,
804 ) -> impl Iterator<Item = PartialScopedSymbol> + 'a {
805 self.symbols
806 .iter(&mut partials.partial_symbol_stacks)
807 .copied()
808 }
809
810 pub fn iter_unordered<'a>(
813 &self,
814 partials: &'a PartialPaths,
815 ) -> impl Iterator<Item = PartialScopedSymbol> + 'a {
816 self.symbols
817 .iter_unordered(&partials.partial_symbol_stacks)
818 .copied()
819 }
820
821 pub fn variable(&self) -> Option<SymbolStackVariable> {
822 self.variable.clone().into_option()
823 }
824
825 fn ensure_both_directions(&mut self, partials: &mut PartialPaths) {
826 self.symbols
827 .ensure_backwards(&mut partials.partial_symbol_stacks);
828 self.symbols
829 .ensure_forwards(&mut partials.partial_symbol_stacks);
830 }
831
832 fn ensure_forwards(&mut self, partials: &mut PartialPaths) {
833 self.symbols
834 .ensure_forwards(&mut partials.partial_symbol_stacks);
835 }
836
837 pub fn largest_symbol_stack_variable(&self) -> u32 {
839 self.variable
840 .into_option()
841 .map(SymbolStackVariable::as_u32)
842 .unwrap_or(0)
843 }
844
845 pub fn largest_scope_stack_variable(&self, partials: &PartialPaths) -> u32 {
847 self.iter_unordered(partials)
850 .filter_map(|symbol| symbol.scopes.into_option())
851 .filter_map(|scopes| scopes.variable.into_option())
852 .map(ScopeStackVariable::as_u32)
853 .max()
854 .unwrap_or(0)
855 }
856}
857
858impl DisplayWithPartialPaths for PartialSymbolStack {
859 fn prepare(&mut self, graph: &StackGraph, partials: &mut PartialPaths) {
860 self.symbols
863 .ensure_forwards(&mut partials.partial_symbol_stacks);
864 let mut symbols = self.symbols;
866 while let Some(mut symbol) = symbols
867 .pop_front(&mut partials.partial_symbol_stacks)
868 .copied()
869 {
870 symbol.prepare(graph, partials);
871 }
872 }
873
874 fn display_with(
875 &self,
876 graph: &StackGraph,
877 partials: &PartialPaths,
878 f: &mut std::fmt::Formatter,
879 ) -> std::fmt::Result {
880 for symbol in self.symbols.iter_reused(&partials.partial_symbol_stacks) {
881 symbol.display_with(graph, partials, f)?;
882 }
883 if let Some(variable) = self.variable.into_option() {
884 if self.symbols.is_empty() {
885 write!(f, "{}", variable)?;
886 } else {
887 write!(f, ",{}", variable)?;
888 }
889 }
890 Ok(())
891 }
892}
893
894#[repr(C)]
900#[derive(Clone, Copy, Niche)]
901pub struct PartialScopeStack {
902 #[niche]
903 scopes: Deque<Handle<Node>>,
904 length: u32,
905 variable: ControlledOption<ScopeStackVariable>,
906}
907
908impl PartialScopeStack {
909 #[inline(always)]
911 pub fn can_match_empty(&self) -> bool {
912 self.scopes.is_empty()
913 }
914
915 #[inline(always)]
917 pub fn can_only_match_empty(&self) -> bool {
918 self.scopes.is_empty() && self.variable.is_none()
919 }
920
921 #[inline(always)]
923 pub fn contains_scopes(&self) -> bool {
924 !self.scopes.is_empty()
925 }
926
927 #[inline(always)]
929 pub fn has_variable(&self) -> bool {
930 self.variable.is_some()
931 }
932
933 #[inline(always)]
934 pub fn len(&self) -> usize {
935 self.length as usize
936 }
937
938 pub fn empty() -> PartialScopeStack {
940 PartialScopeStack {
941 scopes: Deque::empty(),
942 length: 0,
943 variable: ControlledOption::none(),
944 }
945 }
946
947 pub fn from_variable(variable: ScopeStackVariable) -> PartialScopeStack {
949 PartialScopeStack {
950 scopes: Deque::empty(),
951 length: 0,
952 variable: ControlledOption::some(variable),
953 }
954 }
955
956 pub fn have_reversal(&self, partials: &PartialPaths) -> bool {
959 self.scopes.have_reversal(&partials.partial_scope_stacks)
960 }
961
962 pub fn with_offset(mut self, scope_variable_offset: u32) -> PartialScopeStack {
969 match self.variable.into_option() {
970 Some(variable) => {
971 self.variable = ControlledOption::some(variable.with_offset(scope_variable_offset));
972 }
973 None => {}
974 };
975 self
976 }
977
978 pub fn matches(mut self, partials: &mut PartialPaths, mut other: PartialScopeStack) -> bool {
980 while let Some(self_element) = self.pop_front(partials) {
981 if let Some(other_element) = other.pop_front(partials) {
982 if self_element != other_element {
983 return false;
984 }
985 } else {
986 return false;
988 }
989 }
990 if other.contains_scopes() {
991 return false;
993 }
994 self.variable.into_option() == other.variable.into_option()
995 }
996
997 pub fn apply_partial_bindings(
1000 mut self,
1001 partials: &mut PartialPaths,
1002 scope_bindings: &PartialScopeStackBindings,
1003 ) -> Result<PartialScopeStack, PathResolutionError> {
1004 let mut result = match self.variable.into_option() {
1007 Some(variable) => match scope_bindings.get(variable) {
1008 Some(bound) => bound,
1009 None => PartialScopeStack::from_variable(variable),
1010 },
1011 None => PartialScopeStack::empty(),
1012 };
1013
1014 while let Some(scope) = self.pop_back(partials) {
1016 result.push_front(partials, scope);
1017 }
1018 Ok(result)
1019 }
1020
1021 pub fn unify(
1029 self,
1030 partials: &mut PartialPaths,
1031 mut rhs: PartialScopeStack,
1032 bindings: &mut PartialScopeStackBindings,
1033 ) -> Result<PartialScopeStack, PathResolutionError> {
1034 let mut lhs = self;
1035 let original_rhs = rhs;
1036
1037 while lhs.contains_scopes() && rhs.contains_scopes() {
1039 let lhs_front = lhs.pop_front(partials).unwrap();
1040 let rhs_front = rhs.pop_front(partials).unwrap();
1041 if lhs_front != rhs_front {
1042 return Err(PathResolutionError::ScopeStackUnsatisfied);
1043 }
1044 }
1045
1046 if !lhs.contains_scopes() && !rhs.contains_scopes() {
1062 match (lhs.variable.into_option(), rhs.variable.into_option()) {
1063 (None, None) => return Ok(self),
1064 (None, Some(var)) => {
1065 bindings.add(partials, var, PartialScopeStack::empty())?;
1066 return Ok(original_rhs);
1067 }
1068 (Some(var), None) => {
1069 bindings.add(partials, var, PartialScopeStack::empty())?;
1070 return Ok(self);
1071 }
1072 (Some(lhs_var), Some(rhs_var)) => {
1073 bindings.add(partials, rhs_var, PartialScopeStack::from_variable(lhs_var))?;
1074 return Ok(self);
1075 }
1076 }
1077 }
1078
1079 if !lhs.contains_scopes() && lhs.variable.is_none() {
1091 return Err(PathResolutionError::ScopeStackUnsatisfied);
1092 }
1093 if !rhs.contains_scopes() && rhs.variable.is_none() {
1094 return Err(PathResolutionError::ScopeStackUnsatisfied);
1095 }
1096
1097 match (lhs.variable.into_option(), rhs.variable.into_option()) {
1111 (Some(v1), Some(v2)) if v1 == v2 => {
1112 return Err(PathResolutionError::ScopeStackUnsatisfied)
1113 }
1114 _ => {}
1115 }
1116 if lhs.contains_scopes() {
1117 let rhs_variable = rhs.variable.into_option().unwrap();
1118 bindings.add(partials, rhs_variable, lhs)?;
1119 return Ok(self);
1120 }
1121 if rhs.contains_scopes() {
1122 let lhs_variable = lhs.variable.into_option().unwrap();
1123 bindings.add(partials, lhs_variable, rhs)?;
1124 return Ok(original_rhs);
1125 }
1126
1127 unreachable!();
1128 }
1129
1130 pub fn push_front(&mut self, partials: &mut PartialPaths, node: Handle<Node>) {
1135 self.length += 1;
1136 self.scopes
1137 .push_front(&mut partials.partial_scope_stacks, node);
1138 }
1139
1140 pub fn push_back(&mut self, partials: &mut PartialPaths, node: Handle<Node>) {
1145 self.length += 1;
1146 self.scopes
1147 .push_back(&mut partials.partial_scope_stacks, node);
1148 }
1149
1150 pub fn pop_front(&mut self, partials: &mut PartialPaths) -> Option<Handle<Node>> {
1153 let result = self
1154 .scopes
1155 .pop_front(&mut partials.partial_scope_stacks)
1156 .copied();
1157 if result.is_some() {
1158 self.length -= 1;
1159 }
1160 result
1161 }
1162
1163 pub fn pop_back(&mut self, partials: &mut PartialPaths) -> Option<Handle<Node>> {
1166 let result = self
1167 .scopes
1168 .pop_back(&mut partials.partial_scope_stacks)
1169 .copied();
1170 if result.is_some() {
1171 self.length -= 1;
1172 }
1173 result
1174 }
1175
1176 pub fn variable(&self) -> Option<ScopeStackVariable> {
1179 self.variable.into_option()
1180 }
1181
1182 pub fn equals(self, partials: &mut PartialPaths, other: PartialScopeStack) -> bool {
1183 self.scopes
1184 .equals_with(&mut partials.partial_scope_stacks, other.scopes, |a, b| {
1185 *a == *b
1186 })
1187 && equals_option(
1188 self.variable.into_option(),
1189 other.variable.into_option(),
1190 |a, b| a == b,
1191 )
1192 }
1193
1194 pub fn cmp(self, partials: &mut PartialPaths, other: PartialScopeStack) -> std::cmp::Ordering {
1195 std::cmp::Ordering::Equal
1196 .then_with(|| {
1197 self.scopes
1198 .cmp_with(&mut partials.partial_scope_stacks, other.scopes, |a, b| {
1199 a.cmp(b)
1200 })
1201 })
1202 .then_with(|| {
1203 cmp_option(
1204 self.variable.into_option(),
1205 other.variable.into_option(),
1206 |a, b| a.cmp(&b),
1207 )
1208 })
1209 }
1210
1211 pub fn iter_scopes<'a>(
1213 &self,
1214 partials: &'a mut PartialPaths,
1215 ) -> impl Iterator<Item = Handle<Node>> + 'a {
1216 self.scopes
1217 .iter(&mut partials.partial_scope_stacks)
1218 .copied()
1219 }
1220
1221 pub fn iter_unordered<'a>(
1224 &self,
1225 partials: &'a PartialPaths,
1226 ) -> impl Iterator<Item = Handle<Node>> + 'a {
1227 self.scopes
1228 .iter_unordered(&partials.partial_scope_stacks)
1229 .copied()
1230 }
1231
1232 pub fn display<'a>(
1233 self,
1234 graph: &'a StackGraph,
1235 partials: &'a mut PartialPaths,
1236 ) -> impl Display + 'a {
1237 display_with(self, graph, partials)
1238 }
1239
1240 fn ensure_both_directions(&mut self, partials: &mut PartialPaths) {
1241 self.scopes
1242 .ensure_backwards(&mut partials.partial_scope_stacks);
1243 self.scopes
1244 .ensure_forwards(&mut partials.partial_scope_stacks);
1245 }
1246
1247 fn ensure_forwards(&mut self, partials: &mut PartialPaths) {
1248 self.scopes
1249 .ensure_forwards(&mut partials.partial_scope_stacks);
1250 }
1251
1252 pub fn largest_scope_stack_variable(&self) -> u32 {
1254 self.variable
1255 .into_option()
1256 .map(ScopeStackVariable::as_u32)
1257 .unwrap_or(0)
1258 }
1259}
1260
1261impl DisplayWithPartialPaths for PartialScopeStack {
1262 fn prepare(&mut self, _graph: &StackGraph, partials: &mut PartialPaths) {
1263 self.scopes
1264 .ensure_forwards(&mut partials.partial_scope_stacks);
1265 }
1266
1267 fn display_with(
1268 &self,
1269 graph: &StackGraph,
1270 partials: &PartialPaths,
1271 f: &mut std::fmt::Formatter,
1272 ) -> std::fmt::Result {
1273 let mut first = true;
1274 for scope in self.scopes.iter_reused(&partials.partial_scope_stacks) {
1275 if first {
1276 first = false;
1277 } else {
1278 write!(f, ",")?;
1279 }
1280 write!(f, "{:#}", scope.display(graph))?;
1281 }
1282 if let Some(variable) = self.variable.into_option() {
1283 if self.scopes.is_empty() {
1284 write!(f, "{}", variable)?;
1285 } else {
1286 write!(f, ",{}", variable)?;
1287 }
1288 }
1289 Ok(())
1290 }
1291}
1292
1293pub struct PartialSymbolStackBindings {
1297 bindings: SmallVec<[Option<PartialSymbolStack>; 4]>,
1298}
1299
1300impl PartialSymbolStackBindings {
1301 pub fn new() -> PartialSymbolStackBindings {
1303 PartialSymbolStackBindings {
1304 bindings: SmallVec::new(),
1305 }
1306 }
1307
1308 pub fn get(&self, variable: SymbolStackVariable) -> Option<PartialSymbolStack> {
1311 let index = variable.as_usize();
1312 if self.bindings.len() < index {
1313 return None;
1314 }
1315 self.bindings[index - 1]
1316 }
1317
1318 pub fn add(
1321 &mut self,
1322 partials: &mut PartialPaths,
1323 variable: SymbolStackVariable,
1324 mut symbols: PartialSymbolStack,
1325 scope_bindings: &mut PartialScopeStackBindings,
1326 ) -> Result<(), PathResolutionError> {
1327 let index = variable.as_usize();
1328 if self.bindings.len() < index {
1329 self.bindings.resize_with(index, || None);
1330 }
1331 if let Some(old_binding) = self.bindings[index - 1] {
1332 symbols = symbols.unify(partials, old_binding, self, scope_bindings)?;
1333 }
1334 self.bindings[index - 1] = Some(symbols);
1335 Ok(())
1336 }
1337
1338 pub fn display<'a>(
1339 &'a mut self,
1340 graph: &'a StackGraph,
1341 partials: &'a mut PartialPaths,
1342 ) -> impl Display + 'a {
1343 display_with(self, graph, partials)
1344 }
1345}
1346
1347impl<'a> DisplayWithPartialPaths for &'a mut PartialSymbolStackBindings {
1348 fn prepare(&mut self, graph: &StackGraph, partials: &mut PartialPaths) {
1349 for binding in &mut self.bindings {
1350 if let Some(binding) = binding.as_mut() {
1351 binding.prepare(graph, partials);
1352 }
1353 }
1354 }
1355
1356 fn display_with(
1357 &self,
1358 graph: &StackGraph,
1359 partials: &PartialPaths,
1360 f: &mut std::fmt::Formatter,
1361 ) -> std::fmt::Result {
1362 write!(f, "{{")?;
1363 let mut first = true;
1364 for (idx, binding) in self.bindings.iter().enumerate() {
1365 if let Some(binding) = binding.as_ref() {
1366 if first {
1367 first = false;
1368 } else {
1369 write!(f, ", ")?;
1370 }
1371 write!(
1372 f,
1373 "%{} => <{}>",
1374 idx + 1,
1375 display_prepared(*binding, graph, partials)
1376 )?;
1377 }
1378 }
1379 write!(f, "}}")
1380 }
1381}
1382
1383pub struct PartialScopeStackBindings {
1387 bindings: SmallVec<[Option<PartialScopeStack>; 4]>,
1388}
1389
1390impl PartialScopeStackBindings {
1391 pub fn new() -> PartialScopeStackBindings {
1393 PartialScopeStackBindings {
1394 bindings: SmallVec::new(),
1395 }
1396 }
1397
1398 pub fn get(&self, variable: ScopeStackVariable) -> Option<PartialScopeStack> {
1401 let index = variable.as_usize();
1402 if self.bindings.len() < index {
1403 return None;
1404 }
1405 self.bindings[index - 1]
1406 }
1407
1408 pub fn add(
1411 &mut self,
1412 partials: &mut PartialPaths,
1413 variable: ScopeStackVariable,
1414 mut scopes: PartialScopeStack,
1415 ) -> Result<(), PathResolutionError> {
1416 let index = variable.as_usize();
1417 if self.bindings.len() < index {
1418 self.bindings.resize_with(index, || None);
1419 }
1420 if let Some(old_binding) = self.bindings[index - 1] {
1421 scopes = scopes.unify(partials, old_binding, self)?;
1422 }
1423 self.bindings[index - 1] = Some(scopes);
1424 Ok(())
1425 }
1426
1427 pub fn display<'a>(
1428 &'a mut self,
1429 graph: &'a StackGraph,
1430 partials: &'a mut PartialPaths,
1431 ) -> impl Display + 'a {
1432 display_with(self, graph, partials)
1433 }
1434}
1435
1436impl<'a> DisplayWithPartialPaths for &'a mut PartialScopeStackBindings {
1437 fn prepare(&mut self, graph: &StackGraph, partials: &mut PartialPaths) {
1438 for binding in &mut self.bindings {
1439 if let Some(binding) = binding.as_mut() {
1440 binding.prepare(graph, partials);
1441 }
1442 }
1443 }
1444
1445 fn display_with(
1446 &self,
1447 graph: &StackGraph,
1448 partials: &PartialPaths,
1449 f: &mut std::fmt::Formatter,
1450 ) -> std::fmt::Result {
1451 write!(f, "{{")?;
1452 let mut first = true;
1453 for (idx, binding) in self.bindings.iter().enumerate() {
1454 if let Some(binding) = binding.as_ref() {
1455 if first {
1456 first = false;
1457 } else {
1458 write!(f, ", ")?;
1459 }
1460 write!(
1461 f,
1462 "${} => ({})",
1463 idx + 1,
1464 display_prepared(*binding, graph, partials)
1465 )?;
1466 }
1467 }
1468 write!(f, "}}")
1469 }
1470}
1471
1472#[repr(C)]
1476#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
1477pub struct PartialPathEdge {
1478 pub source_node_id: NodeID,
1479 pub precedence: i32,
1480}
1481
1482impl PartialPathEdge {
1483 pub fn shadows(self, other: PartialPathEdge) -> bool {
1486 self.source_node_id == other.source_node_id && self.precedence > other.precedence
1487 }
1488
1489 pub fn display<'a>(
1490 self,
1491 graph: &'a StackGraph,
1492 partials: &'a mut PartialPaths,
1493 ) -> impl Display + 'a {
1494 display_with(self, graph, partials)
1495 }
1496}
1497
1498impl DisplayWithPartialPaths for PartialPathEdge {
1499 fn display_with(
1500 &self,
1501 graph: &StackGraph,
1502 _partials: &PartialPaths,
1503 f: &mut std::fmt::Formatter,
1504 ) -> std::fmt::Result {
1505 match graph.node_for_id(self.source_node_id) {
1506 Some(node) => write!(f, "{:#}", node.display(graph))?,
1507 None => write!(f, "[missing]")?,
1508 }
1509 if self.precedence != 0 {
1510 write!(f, "({})", self.precedence)?;
1511 }
1512 Ok(())
1513 }
1514}
1515
1516#[repr(C)]
1519#[derive(Clone, Copy, Niche)]
1520pub struct PartialPathEdgeList {
1521 #[niche]
1522 edges: Deque<PartialPathEdge>,
1523 length: u32,
1524}
1525
1526impl PartialPathEdgeList {
1527 #[inline(always)]
1529 pub fn is_empty(&self) -> bool {
1530 self.edges.is_empty()
1531 }
1532
1533 #[inline(always)]
1534 pub fn len(&self) -> usize {
1535 self.length as usize
1536 }
1537
1538 pub fn have_reversal(&self, partials: &PartialPaths) -> bool {
1541 self.edges.have_reversal(&partials.partial_path_edges)
1542 }
1543
1544 pub fn empty() -> PartialPathEdgeList {
1546 PartialPathEdgeList {
1547 edges: Deque::empty(),
1548 length: 0,
1549 }
1550 }
1551
1552 pub fn push_front(&mut self, partials: &mut PartialPaths, edge: PartialPathEdge) {
1554 self.length += 1;
1555 self.edges
1556 .push_front(&mut partials.partial_path_edges, edge);
1557 }
1558
1559 pub fn push_back(&mut self, partials: &mut PartialPaths, edge: PartialPathEdge) {
1561 self.length += 1;
1562 self.edges.push_back(&mut partials.partial_path_edges, edge);
1563 }
1564
1565 pub fn pop_front(&mut self, partials: &mut PartialPaths) -> Option<PartialPathEdge> {
1568 let result = self.edges.pop_front(&mut partials.partial_path_edges);
1569 if result.is_some() {
1570 self.length -= 1;
1571 }
1572 result.copied()
1573 }
1574
1575 pub fn pop_back(&mut self, partials: &mut PartialPaths) -> Option<PartialPathEdge> {
1578 let result = self.edges.pop_back(&mut partials.partial_path_edges);
1579 if result.is_some() {
1580 self.length -= 1;
1581 }
1582 result.copied()
1583 }
1584
1585 pub fn display<'a>(
1586 self,
1587 graph: &'a StackGraph,
1588 partials: &'a mut PartialPaths,
1589 ) -> impl Display + 'a {
1590 display_with(self, graph, partials)
1591 }
1592
1593 pub fn shadows(mut self, partials: &mut PartialPaths, mut other: PartialPathEdgeList) -> bool {
1596 while let Some(self_edge) = self.pop_front(partials) {
1597 if let Some(other_edge) = other.pop_front(partials) {
1598 if self_edge.source_node_id != other_edge.source_node_id {
1599 return false;
1600 } else if self_edge.shadows(other_edge) {
1601 return true;
1602 }
1603 } else {
1604 return false;
1605 }
1606 }
1607 false
1608 }
1609
1610 pub fn equals(mut self, partials: &mut PartialPaths, mut other: PartialPathEdgeList) -> bool {
1611 while let Some(self_edge) = self.pop_front(partials) {
1612 if let Some(other_edge) = other.pop_front(partials) {
1613 if self_edge != other_edge {
1614 return false;
1615 }
1616 } else {
1617 return false;
1618 }
1619 }
1620 other.edges.is_empty()
1621 }
1622
1623 pub fn cmp(
1624 mut self,
1625 partials: &mut PartialPaths,
1626 mut other: PartialPathEdgeList,
1627 ) -> std::cmp::Ordering {
1628 use std::cmp::Ordering;
1629 while let Some(self_edge) = self.pop_front(partials) {
1630 if let Some(other_edge) = other.pop_front(partials) {
1631 match self_edge.cmp(&other_edge) {
1632 Ordering::Equal => continue,
1633 result @ _ => return result,
1634 }
1635 } else {
1636 return Ordering::Greater;
1637 }
1638 }
1639 if other.edges.is_empty() {
1640 Ordering::Equal
1641 } else {
1642 Ordering::Less
1643 }
1644 }
1645
1646 pub fn iter<'a>(
1648 &self,
1649 partials: &'a mut PartialPaths,
1650 ) -> impl Iterator<Item = PartialPathEdge> + 'a {
1651 self.edges.iter(&mut partials.partial_path_edges).copied()
1652 }
1653
1654 pub fn iter_unordered<'a>(
1657 &self,
1658 partials: &'a PartialPaths,
1659 ) -> impl Iterator<Item = PartialPathEdge> + 'a {
1660 self.edges
1661 .iter_unordered(&partials.partial_path_edges)
1662 .copied()
1663 }
1664
1665 fn ensure_both_directions(&mut self, partials: &mut PartialPaths) {
1666 self.edges
1667 .ensure_backwards(&mut partials.partial_path_edges);
1668 self.edges.ensure_forwards(&mut partials.partial_path_edges);
1669 }
1670
1671 fn ensure_forwards(&mut self, partials: &mut PartialPaths) {
1672 self.edges.ensure_forwards(&mut partials.partial_path_edges);
1673 }
1674}
1675
1676impl DisplayWithPartialPaths for PartialPathEdgeList {
1677 fn prepare(&mut self, graph: &StackGraph, partials: &mut PartialPaths) {
1678 self.edges.ensure_forwards(&mut partials.partial_path_edges);
1679 let mut edges = self.edges;
1680 while let Some(mut edge) = edges.pop_front(&mut partials.partial_path_edges).copied() {
1681 edge.prepare(graph, partials);
1682 }
1683 }
1684
1685 fn display_with(
1686 &self,
1687 graph: &StackGraph,
1688 partials: &PartialPaths,
1689 f: &mut std::fmt::Formatter,
1690 ) -> std::fmt::Result {
1691 for edge in self.edges.iter_reused(&partials.partial_path_edges) {
1692 edge.display_with(graph, partials, f)?;
1693 }
1694 Ok(())
1695 }
1696}
1697
1698#[repr(C)]
1718#[derive(Clone)]
1719pub struct PartialPath {
1720 pub start_node: Handle<Node>,
1721 pub end_node: Handle<Node>,
1722 pub symbol_stack_precondition: PartialSymbolStack,
1723 pub symbol_stack_postcondition: PartialSymbolStack,
1724 pub scope_stack_precondition: PartialScopeStack,
1725 pub scope_stack_postcondition: PartialScopeStack,
1726 pub edges: PartialPathEdgeList,
1727}
1728
1729impl PartialPath {
1730 pub fn from_node(
1732 graph: &StackGraph,
1733 partials: &mut PartialPaths,
1734 node: Handle<Node>,
1735 ) -> PartialPath {
1736 let initial_symbol_stack = SymbolStackVariable::initial();
1737 let initial_scope_stack = ScopeStackVariable::initial();
1738 let mut symbol_stack_precondition = PartialSymbolStack::from_variable(initial_symbol_stack);
1739 let mut symbol_stack_postcondition =
1740 PartialSymbolStack::from_variable(initial_symbol_stack);
1741 let mut scope_stack_precondition = PartialScopeStack::from_variable(initial_scope_stack);
1742 let mut scope_stack_postcondition = PartialScopeStack::from_variable(initial_scope_stack);
1743
1744 graph[node]
1745 .append_to_partial_stacks(
1746 graph,
1747 partials,
1748 &mut symbol_stack_precondition,
1749 &mut scope_stack_precondition,
1750 &mut symbol_stack_postcondition,
1751 &mut scope_stack_postcondition,
1752 )
1753 .expect("lifting single nodes to partial paths should not fail");
1754
1755 PartialPath {
1756 start_node: node,
1757 end_node: node,
1758 symbol_stack_precondition,
1759 symbol_stack_postcondition,
1760 scope_stack_precondition,
1761 scope_stack_postcondition,
1762 edges: PartialPathEdgeList::empty(),
1763 }
1764 }
1765
1766 pub fn shadows(&self, partials: &mut PartialPaths, other: &PartialPath) -> bool {
1769 self.edges.shadows(partials, other.edges)
1770 }
1771
1772 pub fn equals(&self, partials: &mut PartialPaths, other: &PartialPath) -> bool {
1773 self.start_node == other.start_node
1774 && self.end_node == other.end_node
1775 && self
1776 .symbol_stack_precondition
1777 .equals(partials, other.symbol_stack_precondition)
1778 && self
1779 .symbol_stack_postcondition
1780 .equals(partials, other.symbol_stack_postcondition)
1781 && self
1782 .scope_stack_precondition
1783 .equals(partials, other.scope_stack_precondition)
1784 && self
1785 .scope_stack_postcondition
1786 .equals(partials, other.scope_stack_postcondition)
1787 }
1788
1789 pub fn cmp(
1790 &self,
1791 graph: &StackGraph,
1792 partials: &mut PartialPaths,
1793 other: &PartialPath,
1794 ) -> std::cmp::Ordering {
1795 std::cmp::Ordering::Equal
1796 .then_with(|| self.start_node.cmp(&other.start_node))
1797 .then_with(|| self.end_node.cmp(&other.end_node))
1798 .then_with(|| {
1799 self.symbol_stack_precondition
1800 .cmp(graph, partials, other.symbol_stack_precondition)
1801 })
1802 .then_with(|| {
1803 self.symbol_stack_postcondition.cmp(
1804 graph,
1805 partials,
1806 other.symbol_stack_postcondition,
1807 )
1808 })
1809 .then_with(|| {
1810 self.scope_stack_precondition
1811 .cmp(partials, other.scope_stack_precondition)
1812 })
1813 .then_with(|| {
1814 self.scope_stack_postcondition
1815 .cmp(partials, other.scope_stack_postcondition)
1816 })
1817 }
1818
1819 pub fn starts_at_reference(&self, graph: &StackGraph) -> bool {
1822 graph[self.start_node].is_reference()
1823 && self.symbol_stack_precondition.can_match_empty()
1824 && self.scope_stack_precondition.can_match_empty()
1825 }
1826
1827 pub fn ends_at_definition(&self, graph: &StackGraph) -> bool {
1830 graph[self.end_node].is_definition() && self.symbol_stack_postcondition.can_match_empty()
1831 }
1832
1833 pub fn is_complete(&self, graph: &StackGraph) -> bool {
1836 self.starts_at_reference(graph) && self.ends_at_definition(graph)
1837 }
1838
1839 pub fn starts_at_endpoint(&self, graph: &StackGraph) -> bool {
1840 graph[self.start_node].is_endpoint()
1841 }
1842
1843 pub fn ends_at_endpoint(&self, graph: &StackGraph) -> bool {
1844 graph[self.end_node].is_endpoint()
1845 }
1846
1847 pub fn ends_in_jump(&self, graph: &StackGraph) -> bool {
1848 graph[self.end_node].is_jump_to()
1849 }
1850
1851 pub fn is_cyclic(&self, graph: &StackGraph, partials: &mut PartialPaths) -> Option<Cyclicity> {
1855 if self.start_node != self.end_node {
1858 return None;
1859 }
1860
1861 let lhs = self;
1862 let mut rhs = self.clone();
1863 rhs.ensure_no_overlapping_variables(partials, lhs);
1864
1865 let join = match Self::compute_join(graph, partials, lhs, &rhs) {
1866 Ok(join) => join,
1867 Err(_) => return None,
1868 };
1869
1870 if lhs
1871 .symbol_stack_precondition
1872 .variable
1873 .into_option()
1874 .map_or(false, |v| join.symbol_bindings.get(v).iter().len() > 0)
1875 || lhs
1876 .scope_stack_precondition
1877 .variable
1878 .into_option()
1879 .map_or(false, |v| join.scope_bindings.get(v).iter().len() > 0)
1880 {
1881 Some(Cyclicity::StrengthensPrecondition)
1882 } else if rhs
1883 .symbol_stack_postcondition
1884 .variable
1885 .into_option()
1886 .map_or(false, |v| join.symbol_bindings.get(v).iter().len() > 0)
1887 || rhs
1888 .scope_stack_postcondition
1889 .variable
1890 .into_option()
1891 .map_or(false, |v| join.scope_bindings.get(v).iter().len() > 0)
1892 {
1893 Some(Cyclicity::StrengthensPostcondition)
1894 } else {
1895 Some(Cyclicity::Free)
1896 }
1897 }
1898
1899 pub fn ensure_both_directions(&mut self, partials: &mut PartialPaths) {
1902 self.symbol_stack_precondition
1903 .ensure_both_directions(partials);
1904 self.symbol_stack_postcondition
1905 .ensure_both_directions(partials);
1906 self.scope_stack_precondition
1907 .ensure_both_directions(partials);
1908 self.scope_stack_postcondition
1909 .ensure_both_directions(partials);
1910 self.edges.ensure_both_directions(partials);
1911
1912 let mut stack = self.symbol_stack_precondition;
1913 while let Some(symbol) = stack.pop_front(partials) {
1914 if let Some(mut scopes) = symbol.scopes.into_option() {
1915 scopes.ensure_both_directions(partials);
1916 }
1917 }
1918
1919 let mut stack = self.symbol_stack_postcondition;
1920 while let Some(symbol) = stack.pop_front(partials) {
1921 if let Some(mut scopes) = symbol.scopes.into_option() {
1922 scopes.ensure_both_directions(partials);
1923 }
1924 }
1925 }
1926
1927 pub fn ensure_forwards(&mut self, partials: &mut PartialPaths) {
1929 self.symbol_stack_precondition.ensure_forwards(partials);
1930 self.symbol_stack_postcondition.ensure_forwards(partials);
1931 self.scope_stack_precondition.ensure_forwards(partials);
1932 self.scope_stack_postcondition.ensure_forwards(partials);
1933 self.edges.ensure_forwards(partials);
1934
1935 let mut stack = self.symbol_stack_precondition;
1936 while let Some(symbol) = stack.pop_front(partials) {
1937 if let Some(mut scopes) = symbol.scopes.into_option() {
1938 scopes.ensure_forwards(partials);
1939 }
1940 }
1941
1942 let mut stack = self.symbol_stack_postcondition;
1943 while let Some(symbol) = stack.pop_front(partials) {
1944 if let Some(mut scopes) = symbol.scopes.into_option() {
1945 scopes.ensure_forwards(partials);
1946 }
1947 }
1948 }
1949
1950 pub fn largest_symbol_stack_variable(&self) -> u32 {
1952 self.symbol_stack_precondition
1955 .largest_symbol_stack_variable()
1956 }
1957
1958 pub fn largest_scope_stack_variable(&self, partials: &PartialPaths) -> u32 {
1960 Self::largest_scope_stack_variable_for_partial_stacks(
1961 partials,
1962 &self.symbol_stack_precondition,
1963 &self.scope_stack_precondition,
1964 )
1965 }
1966
1967 fn largest_scope_stack_variable_for_partial_stacks(
1968 partials: &PartialPaths,
1969 symbol_stack_precondition: &PartialSymbolStack,
1970 scope_stack_precondition: &PartialScopeStack,
1971 ) -> u32 {
1972 std::cmp::max(
1975 symbol_stack_precondition.largest_scope_stack_variable(partials),
1976 scope_stack_precondition.largest_scope_stack_variable(),
1977 )
1978 }
1979
1980 pub fn fresh_scope_stack_variable(&self, partials: &PartialPaths) -> ScopeStackVariable {
1983 Self::fresh_scope_stack_variable_for_partial_stack(
1984 partials,
1985 &self.symbol_stack_precondition,
1986 &self.scope_stack_precondition,
1987 )
1988 }
1989
1990 fn fresh_scope_stack_variable_for_partial_stack(
1991 partials: &PartialPaths,
1992 symbol_stack_precondition: &PartialSymbolStack,
1993 scope_stack_precondition: &PartialScopeStack,
1994 ) -> ScopeStackVariable {
1995 ScopeStackVariable::fresher_than(Self::largest_scope_stack_variable_for_partial_stacks(
1996 partials,
1997 symbol_stack_precondition,
1998 scope_stack_precondition,
1999 ))
2000 }
2001
2002 pub fn display<'a>(
2003 &'a self,
2004 graph: &'a StackGraph,
2005 partials: &'a mut PartialPaths,
2006 ) -> impl Display + 'a {
2007 display_with(self, graph, partials)
2008 }
2009}
2010
2011#[derive(Debug, EnumSetType)]
2012pub enum Cyclicity {
2013 Free,
2015 StrengthensPrecondition,
2017 StrengthensPostcondition,
2019}
2020
2021impl<'a> DisplayWithPartialPaths for &'a PartialPath {
2022 fn prepare(&mut self, graph: &StackGraph, partials: &mut PartialPaths) {
2023 self.symbol_stack_precondition
2024 .clone()
2025 .prepare(graph, partials);
2026 self.symbol_stack_postcondition
2027 .clone()
2028 .prepare(graph, partials);
2029 self.scope_stack_precondition
2030 .clone()
2031 .prepare(graph, partials);
2032 self.scope_stack_postcondition
2033 .clone()
2034 .prepare(graph, partials);
2035 }
2036
2037 fn display_with(
2038 &self,
2039 graph: &StackGraph,
2040 partials: &PartialPaths,
2041 f: &mut std::fmt::Formatter,
2042 ) -> std::fmt::Result {
2043 write!(
2044 f,
2045 "<{}> ({}) {} -> {} <{}> ({})",
2046 display_prepared(self.symbol_stack_precondition, graph, partials),
2047 display_prepared(self.scope_stack_precondition, graph, partials),
2048 self.start_node.display(graph),
2049 self.end_node.display(graph),
2050 display_prepared(self.symbol_stack_postcondition, graph, partials),
2051 display_prepared(self.scope_stack_postcondition, graph, partials),
2052 )
2053 }
2054}
2055
2056impl PartialPath {
2057 pub fn ensure_no_overlapping_variables(
2060 &mut self,
2061 partials: &mut PartialPaths,
2062 other: &PartialPath,
2063 ) {
2064 let symbol_variable_offset = other.largest_symbol_stack_variable();
2065 let scope_variable_offset = other.largest_scope_stack_variable(partials);
2066 self.symbol_stack_precondition = self.symbol_stack_precondition.with_offset(
2067 partials,
2068 symbol_variable_offset,
2069 scope_variable_offset,
2070 );
2071 self.symbol_stack_postcondition = self.symbol_stack_postcondition.with_offset(
2072 partials,
2073 symbol_variable_offset,
2074 scope_variable_offset,
2075 );
2076 self.scope_stack_precondition = self
2077 .scope_stack_precondition
2078 .with_offset(scope_variable_offset);
2079 self.scope_stack_postcondition = self
2080 .scope_stack_postcondition
2081 .with_offset(scope_variable_offset);
2082 }
2083
2084 pub fn eliminate_precondition_stack_variables(&mut self, partials: &mut PartialPaths) {
2086 let mut symbol_bindings = PartialSymbolStackBindings::new();
2087 let mut scope_bindings = PartialScopeStackBindings::new();
2088 if let Some(symbol_variable) = self.symbol_stack_precondition.variable() {
2089 symbol_bindings
2090 .add(
2091 partials,
2092 symbol_variable,
2093 PartialSymbolStack::empty(),
2094 &mut scope_bindings,
2095 )
2096 .unwrap();
2097 }
2098 if let Some(scope_variable) = self.scope_stack_precondition.variable() {
2099 scope_bindings
2100 .add(partials, scope_variable, PartialScopeStack::empty())
2101 .unwrap();
2102 }
2103
2104 self.symbol_stack_precondition = self
2105 .symbol_stack_precondition
2106 .apply_partial_bindings(partials, &symbol_bindings, &scope_bindings)
2107 .unwrap();
2108 self.scope_stack_precondition = self
2109 .scope_stack_precondition
2110 .apply_partial_bindings(partials, &scope_bindings)
2111 .unwrap();
2112
2113 self.symbol_stack_postcondition = self
2114 .symbol_stack_postcondition
2115 .apply_partial_bindings(partials, &symbol_bindings, &scope_bindings)
2116 .unwrap();
2117 self.scope_stack_postcondition = self
2118 .scope_stack_postcondition
2119 .apply_partial_bindings(partials, &scope_bindings)
2120 .unwrap();
2121 }
2122
2123 pub fn append(
2126 &mut self,
2127 graph: &StackGraph,
2128 partials: &mut PartialPaths,
2129 edge: Edge,
2130 ) -> Result<(), PathResolutionError> {
2131 if edge.source != self.end_node {
2132 return Err(PathResolutionError::IncorrectSourceNode);
2133 }
2134
2135 graph[edge.sink].append_to_partial_stacks(
2136 graph,
2137 partials,
2138 &mut self.symbol_stack_precondition,
2139 &mut self.scope_stack_precondition,
2140 &mut self.symbol_stack_postcondition,
2141 &mut self.scope_stack_postcondition,
2142 )?;
2143
2144 self.end_node = edge.sink;
2145 self.edges.push_back(
2146 partials,
2147 PartialPathEdge {
2148 source_node_id: graph[edge.source].id(),
2149 precedence: edge.precedence,
2150 },
2151 );
2152
2153 self.resolve_from_postcondition(graph, partials)?;
2154
2155 Ok(())
2156 }
2157
2158 pub fn resolve_from_postcondition(
2162 &mut self,
2163 graph: &StackGraph,
2164 partials: &mut PartialPaths,
2165 ) -> Result<(), PathResolutionError> {
2166 if !graph[self.end_node].is_jump_to() {
2167 return Ok(());
2168 }
2169 if self.scope_stack_postcondition.can_only_match_empty() {
2170 return Err(PathResolutionError::EmptyScopeStack);
2171 }
2172 if !self.scope_stack_postcondition.contains_scopes() {
2173 return Ok(());
2174 }
2175 let top_scope = self.scope_stack_postcondition.pop_front(partials).unwrap();
2176 self.edges.push_back(
2177 partials,
2178 PartialPathEdge {
2179 source_node_id: graph[self.end_node].id(),
2180 precedence: 0,
2181 },
2182 );
2183 self.end_node = top_scope;
2184 Ok(())
2185 }
2186
2187 pub fn resolve_to_node(
2192 &mut self,
2193 graph: &StackGraph,
2194 partials: &mut PartialPaths,
2195 node: Handle<Node>,
2196 ) -> Result<(), PathResolutionError> {
2197 if !graph[self.end_node].is_jump_to() {
2198 return Ok(());
2199 }
2200
2201 let scope_variable = match self.scope_stack_postcondition.variable() {
2202 Some(scope_variable) => scope_variable,
2203 None => return Err(PathResolutionError::ScopeStackUnsatisfied),
2204 };
2205 let mut scope_stack = PartialScopeStack::from_variable(scope_variable);
2206 scope_stack.push_front(partials, node);
2207
2208 let symbol_bindings = PartialSymbolStackBindings::new();
2209 let mut scope_bindings = PartialScopeStackBindings::new();
2210 scope_bindings
2211 .add(partials, scope_variable, scope_stack)
2212 .unwrap();
2213
2214 self.symbol_stack_precondition = self
2215 .symbol_stack_precondition
2216 .apply_partial_bindings(partials, &symbol_bindings, &scope_bindings)
2217 .unwrap();
2218 self.scope_stack_precondition = self
2219 .scope_stack_precondition
2220 .apply_partial_bindings(partials, &scope_bindings)
2221 .unwrap();
2222
2223 self.end_node = node;
2224
2225 Ok(())
2226 }
2227}
2228
2229impl Node {
2230 pub(crate) fn append_to_partial_stacks(
2233 &self,
2234 graph: &StackGraph,
2235 partials: &mut PartialPaths,
2236 symbol_stack_precondition: &mut PartialSymbolStack,
2237 scope_stack_precondition: &mut PartialScopeStack,
2238 symbol_stack_postcondition: &mut PartialSymbolStack,
2239 scope_stack_postcondition: &mut PartialScopeStack,
2240 ) -> Result<(), PathResolutionError> {
2241 match self {
2242 Self::DropScopes(_) => {
2243 *scope_stack_postcondition = PartialScopeStack::empty();
2244 }
2245 Self::JumpTo(_) => {}
2246 Self::PopScopedSymbol(sink) => {
2247 if let Some(top) = symbol_stack_postcondition.pop_front(partials) {
2250 if top.symbol != sink.symbol {
2251 return Err(PathResolutionError::IncorrectPoppedSymbol);
2252 }
2253 let new_scope_stack = match top.scopes.into_option() {
2254 Some(scopes) => scopes,
2255 None => return Err(PathResolutionError::MissingAttachedScopeList),
2256 };
2257 *scope_stack_postcondition = new_scope_stack;
2258 } else if symbol_stack_postcondition.has_variable() {
2259 let scope_stack_variable =
2263 PartialPath::fresh_scope_stack_variable_for_partial_stack(
2264 partials,
2265 symbol_stack_precondition,
2266 scope_stack_precondition,
2267 );
2268 let precondition_symbol = PartialScopedSymbol {
2269 symbol: sink.symbol,
2270 scopes: ControlledOption::some(PartialScopeStack::from_variable(
2271 scope_stack_variable,
2272 )),
2273 };
2274 symbol_stack_precondition.push_back(partials, precondition_symbol);
2280 *scope_stack_postcondition =
2281 PartialScopeStack::from_variable(scope_stack_variable);
2282 } else {
2283 return Err(PathResolutionError::SymbolStackUnsatisfied);
2286 }
2287 }
2288 Self::PopSymbol(sink) => {
2289 if let Some(top) = symbol_stack_postcondition.pop_front(partials) {
2291 if top.symbol != sink.symbol {
2292 return Err(PathResolutionError::IncorrectPoppedSymbol);
2293 }
2294 if top.scopes.is_some() {
2295 return Err(PathResolutionError::UnexpectedAttachedScopeList);
2296 }
2297 } else if symbol_stack_postcondition.has_variable() {
2298 let precondition_symbol = PartialScopedSymbol {
2302 symbol: sink.symbol,
2303 scopes: ControlledOption::none(),
2304 };
2305 symbol_stack_precondition.push_back(partials, precondition_symbol);
2311 } else {
2312 return Err(PathResolutionError::SymbolStackUnsatisfied);
2315 }
2316 }
2317 Self::PushScopedSymbol(sink) => {
2318 let sink_symbol = sink.symbol;
2322 let sink_scope = graph
2323 .node_for_id(sink.scope)
2324 .ok_or(PathResolutionError::UnknownAttachedScope)?;
2325 let mut attached_scopes = scope_stack_postcondition.clone();
2326 attached_scopes.push_front(partials, sink_scope);
2327 let postcondition_symbol = PartialScopedSymbol {
2328 symbol: sink_symbol,
2329 scopes: ControlledOption::some(attached_scopes),
2330 };
2331 symbol_stack_postcondition.push_front(partials, postcondition_symbol);
2332 }
2333 Self::PushSymbol(sink) => {
2334 let sink_symbol = sink.symbol;
2338 let postcondition_symbol = PartialScopedSymbol {
2339 symbol: sink_symbol,
2340 scopes: ControlledOption::none(),
2341 };
2342 symbol_stack_postcondition.push_front(partials, postcondition_symbol);
2343 }
2344 Self::Root(_) => {}
2345 Self::Scope(_) => {}
2346 }
2347 Ok(())
2348 }
2349
2350 fn halfopen_closed_partial_precondition(
2372 &self,
2373 partials: &mut PartialPaths,
2374 symbol_stack: &mut PartialSymbolStack,
2375 scope_stack: &mut PartialScopeStack,
2376 ) -> Result<(), PathResolutionError> {
2377 match self {
2378 Node::DropScopes(_) => {}
2379 Node::JumpTo(_) => {}
2380 Node::PopScopedSymbol(node) => {
2381 let symbol = symbol_stack
2382 .pop_front(partials)
2383 .ok_or(PathResolutionError::EmptySymbolStack)?;
2384 if symbol.symbol != node.symbol {
2385 return Err(PathResolutionError::IncorrectPoppedSymbol);
2386 }
2387 *scope_stack = symbol.scopes.into_option().unwrap();
2388 }
2389 Node::PopSymbol(node) => {
2390 let symbol = symbol_stack
2391 .pop_front(partials)
2392 .ok_or(PathResolutionError::EmptySymbolStack)?;
2393 if symbol.symbol != node.symbol {
2394 return Err(PathResolutionError::IncorrectPoppedSymbol);
2395 }
2396 }
2397 Node::PushScopedSymbol(_) => {}
2398 Node::PushSymbol(_) => {}
2399 Node::Root(_) => {}
2400 Node::Scope(_) => {}
2401 };
2402 Ok(())
2403 }
2404
2405 fn halfopen_closed_partial_postcondition(
2427 &self,
2428 partials: &mut PartialPaths,
2429 symbol_stack: &mut PartialSymbolStack,
2430 _scope_stack: &mut PartialScopeStack,
2431 ) -> Result<(), PathResolutionError> {
2432 match self {
2433 Self::DropScopes(_) => {}
2434 Self::JumpTo(_) => {}
2435 Self::PopScopedSymbol(_) => {}
2436 Self::PopSymbol(_) => {}
2437 Self::PushScopedSymbol(node) => {
2438 let symbol = symbol_stack
2439 .pop_front(partials)
2440 .ok_or(PathResolutionError::EmptySymbolStack)?;
2441 if symbol.symbol != node.symbol {
2442 return Err(PathResolutionError::IncorrectPoppedSymbol);
2443 }
2444 }
2445 Self::PushSymbol(node) => {
2446 let symbol = symbol_stack
2447 .pop_front(partials)
2448 .ok_or(PathResolutionError::EmptySymbolStack)?;
2449 if symbol.symbol != node.symbol {
2450 return Err(PathResolutionError::IncorrectPoppedSymbol);
2451 }
2452 }
2453 Self::Root(_) => {}
2454 Self::Scope(_) => {}
2455 };
2456 Ok(())
2457 }
2458}
2459
2460impl PartialPath {
2464 #[cfg_attr(not(feature = "copious-debugging"), allow(unused_variables))]
2472 pub fn concatenate(
2473 &mut self,
2474 graph: &StackGraph,
2475 partials: &mut PartialPaths,
2476 rhs: &PartialPath,
2477 ) -> Result<(), PathResolutionError> {
2478 let lhs = self;
2479
2480 #[cfg_attr(not(feature = "copious-debugging"), allow(unused_mut))]
2481 let mut join = Self::compute_join(graph, partials, lhs, rhs)?;
2482 #[cfg(feature = "copious-debugging")]
2483 {
2484 let unified_symbol_stack = join
2485 .unified_symbol_stack
2486 .display(graph, partials)
2487 .to_string();
2488 let unified_scope_stack = join
2489 .unified_scope_stack
2490 .display(graph, partials)
2491 .to_string();
2492 let symbol_bindings = join.symbol_bindings.display(graph, partials).to_string();
2493 let scope_bindings = join.scope_bindings.display(graph, partials).to_string();
2494 copious_debugging!(
2495 " via <{}> ({}) {} {}",
2496 unified_symbol_stack,
2497 unified_scope_stack,
2498 symbol_bindings,
2499 scope_bindings,
2500 );
2501 }
2502
2503 lhs.symbol_stack_precondition = lhs.symbol_stack_precondition.apply_partial_bindings(
2504 partials,
2505 &join.symbol_bindings,
2506 &join.scope_bindings,
2507 )?;
2508 lhs.symbol_stack_postcondition = rhs.symbol_stack_postcondition.apply_partial_bindings(
2509 partials,
2510 &join.symbol_bindings,
2511 &join.scope_bindings,
2512 )?;
2513
2514 lhs.scope_stack_precondition = lhs
2515 .scope_stack_precondition
2516 .apply_partial_bindings(partials, &join.scope_bindings)?;
2517 lhs.scope_stack_postcondition = rhs
2518 .scope_stack_postcondition
2519 .apply_partial_bindings(partials, &join.scope_bindings)?;
2520
2521 let mut edges = rhs.edges;
2522 while let Some(edge) = edges.pop_front(partials) {
2523 lhs.edges.push_back(partials, edge);
2524 }
2525 lhs.end_node = rhs.end_node;
2526
2527 lhs.resolve_from_postcondition(graph, partials)?;
2528
2529 Ok(())
2530 }
2531
2532 fn compute_join(
2535 graph: &StackGraph,
2536 partials: &mut PartialPaths,
2537 lhs: &PartialPath,
2538 rhs: &PartialPath,
2539 ) -> Result<Join, PathResolutionError> {
2540 if lhs.end_node != rhs.start_node {
2541 return Err(PathResolutionError::IncorrectSourceNode);
2542 }
2543
2544 let mut lhs_symbol_stack_postcondition = lhs.symbol_stack_postcondition;
2546 let mut lhs_scope_stack_postcondition = lhs.scope_stack_postcondition;
2547 let mut rhs_symbol_stack_precondition = rhs.symbol_stack_precondition;
2548 let mut rhs_scope_stack_precondition = rhs.scope_stack_precondition;
2549 graph[lhs.end_node]
2550 .halfopen_closed_partial_postcondition(
2551 partials,
2552 &mut lhs_symbol_stack_postcondition,
2553 &mut lhs_scope_stack_postcondition,
2554 )
2555 .unwrap_or_else(|e| {
2556 panic!(
2557 "failed to halfopen postcondition of {}: {:?}",
2558 lhs.display(graph, partials),
2559 e
2560 );
2561 });
2562 graph[rhs.start_node]
2563 .halfopen_closed_partial_precondition(
2564 partials,
2565 &mut rhs_symbol_stack_precondition,
2566 &mut rhs_scope_stack_precondition,
2567 )
2568 .unwrap_or_else(|e| {
2569 panic!(
2570 "failed to halfopen postcondition of {}: {:?}",
2571 rhs.display(graph, partials),
2572 e
2573 );
2574 });
2575
2576 let mut symbol_bindings = PartialSymbolStackBindings::new();
2577 let mut scope_bindings = PartialScopeStackBindings::new();
2578 let unified_symbol_stack = lhs_symbol_stack_postcondition.unify(
2579 partials,
2580 rhs_symbol_stack_precondition,
2581 &mut symbol_bindings,
2582 &mut scope_bindings,
2583 )?;
2584 let unified_scope_stack = lhs_scope_stack_postcondition.unify(
2585 partials,
2586 rhs_scope_stack_precondition,
2587 &mut scope_bindings,
2588 )?;
2589
2590 Ok(Join {
2591 unified_symbol_stack,
2592 unified_scope_stack,
2593 symbol_bindings,
2594 scope_bindings,
2595 })
2596 }
2597}
2598
2599struct Join {
2600 #[cfg_attr(not(feature = "copious-debugging"), allow(dead_code))]
2601 pub unified_symbol_stack: PartialSymbolStack,
2602 #[cfg_attr(not(feature = "copious-debugging"), allow(dead_code))]
2603 pub unified_scope_stack: PartialScopeStack,
2604 pub symbol_bindings: PartialSymbolStackBindings,
2605 pub scope_bindings: PartialScopeStackBindings,
2606}
2607
2608pub struct PartialPaths {
2614 pub(crate) partial_symbol_stacks: DequeArena<PartialScopedSymbol>,
2615 pub(crate) partial_scope_stacks: DequeArena<Handle<Node>>,
2616 pub(crate) partial_path_edges: DequeArena<PartialPathEdge>,
2617}
2618
2619impl PartialPaths {
2620 pub fn new() -> PartialPaths {
2621 PartialPaths {
2622 partial_symbol_stacks: Deque::new_arena(),
2623 partial_scope_stacks: Deque::new_arena(),
2624 partial_path_edges: Deque::new_arena(),
2625 }
2626 }
2627
2628 #[cfg_attr(not(feature = "storage"), allow(dead_code))]
2629 pub(crate) fn clear(&mut self) {
2630 self.partial_symbol_stacks.clear();
2631 self.partial_scope_stacks.clear();
2632 self.partial_path_edges.clear();
2633 }
2634}