Skip to main content

rvsdg/
edge.rs

1use super::{Context, id};
2use std::fmt;
3
4/// An user port
5#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash)]
6pub enum User {
7    Input(Input<id::AnyNode>),
8    Result(Result),
9}
10
11/// An origin port
12#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
13pub enum Origin {
14    Output(Output<id::AnyNode>),
15    Argument(Argument),
16}
17
18/// Input `id` belonging to `node`
19pub struct Input<K> {
20    pub node: id::Node<K>,
21    pub id: id::Input,
22}
23
24/// Output `id` belonging to `node`
25pub struct Output<K> {
26    pub node: id::Node<K>,
27    pub id: id::Output,
28}
29
30/// Argument `id` belonging to `region`
31#[derive(Clone, Copy, PartialEq, Eq, Hash)]
32pub struct Argument {
33    pub region: id::Region,
34    pub id: id::Argument,
35}
36
37/// Result `id` belonging to `region`
38#[derive(Clone, Copy, PartialEq, Eq, Hash)]
39pub struct Result {
40    pub region: id::Region,
41    pub id: id::Result,
42}
43
44impl<K> Output<K> {
45    pub fn upcast(self) -> Output<id::AnyNode> {
46        Output {
47            node: id::Node::new(self.node.id),
48            id: self.id,
49        }
50    }
51}
52
53impl<K> Input<K> {
54    pub fn upcast(self) -> Input<id::AnyNode> {
55        Input {
56            node: id::Node::new(self.node.id),
57            id: self.id,
58        }
59    }
60}
61
62impl Context {
63    pub(crate) fn user_associated_node(&self, user: User) -> id::AnyNode {
64        match user {
65            User::Input(input) => input.node.id,
66            User::Result(result) => self.regions[result.region].container_node,
67        }
68    }
69    pub(crate) fn origin_associated_node(&self, origin: Origin) -> id::AnyNode {
70        match origin {
71            Origin::Output(output) => output.node.id,
72            Origin::Argument(argument) => self.regions[argument.region].container_node,
73        }
74    }
75
76    /// Traverse nodes from `user` invoking `f` for each node `user` directly or indirectly depends on.
77    pub fn visit_nodes_upwards<T, F>(&self, user: impl Into<User>, f: &mut F) -> Option<T>
78    where
79        F: FnMut(&Self, id::AnyNode) -> Option<T>,
80    {
81        let user = user.into();
82        match user {
83            User::Input(input) => {
84                if let Some(t) = f(self, input.node.id) {
85                    return Some(t);
86                }
87
88                let onode = self
89                    .get_user(input)
90                    .map(|origin| self.origin_associated_node(origin))?;
91
92                self.inputs(onode)
93                    .map(User::from)
94                    .find_map(|user| self.visit_nodes_upwards(user, f))
95            }
96            User::Result(result) => {
97                let node_id = self.regions[result.region].container_node;
98
99                if let Some(t) = f(self, node_id) {
100                    return Some(t);
101                }
102
103                self.inputs(node_id)
104                    .map(User::from)
105                    .find_map(|user| self.visit_nodes_upwards(user, f))
106            }
107        }
108    }
109}
110
111impl<K> Clone for Input<K> {
112    fn clone(&self) -> Self {
113        *self
114    }
115}
116impl<K> Clone for Output<K> {
117    fn clone(&self) -> Self {
118        *self
119    }
120}
121
122impl<K> Copy for Input<K> {}
123impl<K> Copy for Output<K> {}
124
125impl<K> PartialEq for Output<K> {
126    fn eq(&self, other: &Self) -> bool {
127        self.node == other.node && self.id == other.id
128    }
129}
130impl<K> Eq for Output<K> {}
131
132impl<K> std::hash::Hash for Output<K> {
133    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
134        self.node.id.hash(state);
135        self.id.hash(state);
136    }
137}
138
139impl<K> PartialEq for Input<K> {
140    fn eq(&self, other: &Self) -> bool {
141        self.node == other.node && self.id == other.id
142    }
143}
144impl<K> Eq for Input<K> {}
145
146impl<K> std::hash::Hash for Input<K> {
147    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
148        self.node.id.hash(state);
149        self.id.hash(state);
150    }
151}
152
153impl<K> From<Input<K>> for User {
154    fn from(input: Input<K>) -> Self {
155        User::Input(input.upcast())
156    }
157}
158
159impl From<Result> for User {
160    fn from(result: Result) -> Self {
161        User::Result(result)
162    }
163}
164
165impl<K> From<Output<K>> for Origin {
166    fn from(output: Output<K>) -> Self {
167        Origin::Output(output.upcast())
168    }
169}
170
171impl From<Argument> for Origin {
172    fn from(argument: Argument) -> Self {
173        Origin::Argument(argument)
174    }
175}
176
177impl<K> fmt::Display for Input<K> {
178    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179        write!(f, "{}·{}", self.node.id, self.id)
180    }
181}
182
183impl<K> fmt::Display for Output<K> {
184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185        write!(f, "{}·{}", self.node.id, self.id)
186    }
187}
188
189impl fmt::Display for Argument {
190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191        write!(f, "{}·{}", self.region, self.id)
192    }
193}
194
195impl fmt::Display for Result {
196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197        write!(f, "{}·{}", self.region, self.id)
198    }
199}
200
201impl<K> fmt::Debug for Input<K> {
202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203        write!(f, "{}·{}", self.node.id, self.id)
204    }
205}
206
207impl<K> fmt::Debug for Output<K> {
208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209        write!(f, "{}·{}", self.node.id, self.id)
210    }
211}
212
213impl fmt::Debug for Argument {
214    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215        write!(f, "{}·{}", self.region, self.id)
216    }
217}
218
219impl fmt::Debug for Result {
220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221        write!(f, "{}·{}", self.region, self.id)
222    }
223}
224
225impl fmt::Display for Origin {
226    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227        match self {
228            Origin::Output(output) => output.fmt(f),
229            Origin::Argument(argument) => argument.fmt(f),
230        }
231    }
232}
233
234impl fmt::Display for User {
235    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236        match self {
237            User::Input(input) => input.fmt(f),
238            User::Result(result) => result.fmt(f),
239        }
240    }
241}