morphir_core/traversal/
cursor.rs1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum CursorSegment {
6 Distribution,
7 Package(String),
8 Dependency(String),
9 Module(String),
10 Type(String),
11 Value(String),
12 Constructor(String),
13 Field(String),
14 Argument(usize),
15 PatternCase(usize),
16 LetBinding(String),
17 Branch(&'static str),
18}
19
20impl fmt::Display for CursorSegment {
21 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Self::Distribution => formatter.write_str("distribution"),
24 Self::Package(name) => write!(formatter, "package:{name}"),
25 Self::Dependency(name) => write!(formatter, "dependency:{name}"),
26 Self::Module(name) => write!(formatter, "module:{name}"),
27 Self::Type(name) => write!(formatter, "type:{name}"),
28 Self::Value(name) => write!(formatter, "value:{name}"),
29 Self::Constructor(name) => write!(formatter, "constructor:{name}"),
30 Self::Field(name) => write!(formatter, "field:{name}"),
31 Self::Argument(index) => write!(formatter, "argument:{index}"),
32 Self::PatternCase(index) => write!(formatter, "pattern-case:{index}"),
33 Self::LetBinding(name) => write!(formatter, "let-binding:{name}"),
34 Self::Branch(name) => write!(formatter, "branch:{name}"),
35 }
36 }
37}
38
39#[derive(Debug, Clone, Default, PartialEq, Eq)]
41pub struct IrCursor {
42 segments: Vec<CursorSegment>,
43}
44
45impl IrCursor {
46 pub fn root() -> Self {
48 Self::default()
49 }
50
51 pub fn from_segments(segments: impl IntoIterator<Item = CursorSegment>) -> Self {
52 Self {
53 segments: segments.into_iter().collect(),
54 }
55 }
56
57 pub fn is_root(&self) -> bool {
58 self.segments.is_empty()
59 }
60
61 pub fn segments(&self) -> &[CursorSegment] {
62 &self.segments
63 }
64
65 pub fn child(mut self, segment: CursorSegment) -> Self {
67 self.segments.push(segment);
68 self
69 }
70
71 pub fn with_segment<R>(
73 &mut self,
74 segment: CursorSegment,
75 operation: impl FnOnce(&mut Self) -> R,
76 ) -> R {
77 self.segments.push(segment);
78 let result = operation(self);
79 self.segments.pop();
80 result
81 }
82}
83
84impl fmt::Display for IrCursor {
85 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
86 let path = self
87 .segments
88 .iter()
89 .map(ToString::to_string)
90 .collect::<Vec<_>>()
91 .join("/");
92 formatter.write_str(&path)
93 }
94}