stack_graphs/serde/
partial.rs

1// -*- coding: utf-8 -*-
2// ------------------------------------------------------------------------------------------------
3// Copyright © 2023, stack-graphs authors.
4// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
5// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
6// ------------------------------------------------------------------------------------------------
7
8use crate::partial::PartialPaths;
9
10use super::Error;
11use super::NodeID;
12
13#[derive(Clone, Debug, Eq, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
15#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
16pub struct PartialPath {
17    pub(crate) start_node: NodeID,
18    pub(crate) end_node: NodeID,
19    pub(crate) symbol_stack_precondition: PartialSymbolStack,
20    pub(crate) symbol_stack_postcondition: PartialSymbolStack,
21    pub(crate) scope_stack_precondition: PartialScopeStack,
22    pub(crate) scope_stack_postcondition: PartialScopeStack,
23    pub(crate) edges: PartialPathEdgeList,
24}
25
26impl PartialPath {
27    pub fn from_partial_path(
28        graph: &crate::graph::StackGraph,
29        partials: &mut PartialPaths,
30        value: &crate::partial::PartialPath,
31    ) -> Self {
32        Self {
33            start_node: NodeID::from_node(graph, value.start_node),
34            end_node: NodeID::from_node(graph, value.end_node),
35            symbol_stack_precondition: PartialSymbolStack::from_partial_symbol_stack(
36                graph,
37                partials,
38                &value.symbol_stack_precondition,
39            ),
40            symbol_stack_postcondition: PartialSymbolStack::from_partial_symbol_stack(
41                graph,
42                partials,
43                &value.symbol_stack_postcondition,
44            ),
45            scope_stack_precondition: PartialScopeStack::from_partial_scope_stack(
46                graph,
47                partials,
48                &value.scope_stack_precondition,
49            ),
50            scope_stack_postcondition: PartialScopeStack::from_partial_scope_stack(
51                graph,
52                partials,
53                &value.scope_stack_postcondition,
54            ),
55            edges: PartialPathEdgeList::from_partial_path_edge_list(graph, partials, &value.edges),
56        }
57    }
58
59    pub fn to_partial_path(
60        &self,
61        graph: &mut crate::graph::StackGraph,
62        partials: &mut PartialPaths,
63    ) -> Result<crate::partial::PartialPath, Error> {
64        Ok(crate::partial::PartialPath {
65            start_node: self.start_node.to_node(graph)?,
66            end_node: self.end_node.to_node(graph)?,
67            symbol_stack_precondition: self
68                .symbol_stack_precondition
69                .to_partial_symbol_stack(graph, partials)?,
70            symbol_stack_postcondition: self
71                .symbol_stack_postcondition
72                .to_partial_symbol_stack(graph, partials)?,
73            scope_stack_precondition: self
74                .scope_stack_precondition
75                .to_partial_scope_stack(graph, partials)?,
76            scope_stack_postcondition: self
77                .scope_stack_postcondition
78                .to_partial_scope_stack(graph, partials)?,
79            edges: self.edges.to_partial_path_edge_list(graph, partials)?,
80        })
81    }
82}
83
84#[derive(Clone, Debug, Eq, PartialEq)]
85#[cfg_attr(
86    feature = "serde",
87    serde_with::skip_serializing_none, // must come before derive
88    derive(serde::Deserialize, serde::Serialize),
89)]
90#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
91pub struct PartialScopeStack {
92    pub(crate) scopes: Vec<NodeID>,
93    variable: Option<ScopeStackVariable>,
94}
95
96impl PartialScopeStack {
97    pub fn from_partial_scope_stack(
98        graph: &crate::graph::StackGraph,
99        partials: &mut PartialPaths,
100        value: &crate::partial::PartialScopeStack,
101    ) -> Self {
102        let mut value = *value;
103        let mut scopes = Vec::new();
104        while let Some(scope) = value.pop_front(partials) {
105            scopes.push(NodeID::from_node(graph, scope));
106        }
107        Self {
108            scopes,
109            variable: value
110                .variable()
111                .map(|v| ScopeStackVariable::from_scope_stack_variable(v)),
112        }
113    }
114
115    pub fn to_partial_scope_stack(
116        &self,
117        graph: &mut crate::graph::StackGraph,
118        partials: &mut PartialPaths,
119    ) -> Result<crate::partial::PartialScopeStack, Error> {
120        let mut value = match &self.variable {
121            Some(variable) => crate::partial::PartialScopeStack::from_variable(
122                variable.to_scope_stack_variable()?,
123            ),
124            None => crate::partial::PartialScopeStack::empty(),
125        };
126        for scope in &self.scopes {
127            let scope = scope.to_node(graph)?;
128            value.push_back(partials, scope);
129        }
130        Ok(value)
131    }
132}
133
134#[derive(Clone, Debug, Eq, PartialEq)]
135#[cfg_attr(
136    feature = "serde",
137    derive(serde::Deserialize, serde::Serialize),
138    serde(transparent)
139)]
140#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
141pub struct ScopeStackVariable(u32);
142
143impl ScopeStackVariable {
144    pub fn from_scope_stack_variable(value: crate::partial::ScopeStackVariable) -> Self {
145        Self(value.as_u32())
146    }
147
148    pub fn to_scope_stack_variable(&self) -> Result<crate::partial::ScopeStackVariable, Error> {
149        crate::partial::ScopeStackVariable::new(self.0)
150            .ok_or_else(|| Error::InvalidStackVariable(self.0))
151    }
152}
153
154#[derive(Clone, Debug, Eq, PartialEq)]
155#[cfg_attr(
156    feature = "serde",
157    serde_with::skip_serializing_none, // must come before derive
158    derive(serde::Deserialize, serde::Serialize),
159)]
160#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
161pub struct PartialSymbolStack {
162    pub(crate) symbols: Vec<PartialScopedSymbol>,
163    variable: Option<SymbolStackVariable>,
164}
165
166impl PartialSymbolStack {
167    pub fn from_partial_symbol_stack(
168        graph: &crate::graph::StackGraph,
169        partials: &mut PartialPaths,
170        value: &crate::partial::PartialSymbolStack,
171    ) -> Self {
172        let mut value = *value;
173        let mut symbols = Vec::new();
174        while let Some(symbol) = value.pop_front(partials) {
175            symbols.push(PartialScopedSymbol::from_partial_scoped_symbol(
176                graph, partials, &symbol,
177            ));
178        }
179        Self {
180            symbols,
181            variable: value
182                .variable()
183                .map(|v| SymbolStackVariable::from_symbol_stack_variable(v)),
184        }
185    }
186
187    pub fn to_partial_symbol_stack(
188        &self,
189        graph: &mut crate::graph::StackGraph,
190        partials: &mut PartialPaths,
191    ) -> Result<crate::partial::PartialSymbolStack, Error> {
192        let mut value = match &self.variable {
193            Some(variable) => crate::partial::PartialSymbolStack::from_variable(
194                variable.to_symbol_stack_variable()?,
195            ),
196            None => crate::partial::PartialSymbolStack::empty(),
197        };
198        for symbol in &self.symbols {
199            let symbol = symbol.to_partial_scoped_symbol(graph, partials)?;
200            value.push_back(partials, symbol);
201        }
202        Ok(value)
203    }
204}
205
206#[derive(Clone, Debug, Eq, PartialEq)]
207#[cfg_attr(
208    feature = "serde",
209    derive(serde::Deserialize, serde::Serialize),
210    serde(transparent)
211)]
212#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
213pub struct SymbolStackVariable(u32);
214
215impl SymbolStackVariable {
216    pub fn from_symbol_stack_variable(value: crate::partial::SymbolStackVariable) -> Self {
217        Self(value.as_u32())
218    }
219
220    pub fn to_symbol_stack_variable(&self) -> Result<crate::partial::SymbolStackVariable, Error> {
221        crate::partial::SymbolStackVariable::new(self.0)
222            .ok_or_else(|| Error::InvalidStackVariable(self.0))
223    }
224}
225
226#[derive(Clone, Debug, Eq, PartialEq)]
227#[cfg_attr(
228    feature = "serde",
229    serde_with::skip_serializing_none, // must come before derive
230    derive(serde::Deserialize, serde::Serialize),
231)]
232#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
233pub struct PartialScopedSymbol {
234    symbol: String,
235    pub(crate) scopes: Option<PartialScopeStack>,
236}
237
238impl PartialScopedSymbol {
239    pub fn from_partial_scoped_symbol(
240        graph: &crate::graph::StackGraph,
241        partials: &mut crate::partial::PartialPaths,
242        value: &crate::partial::PartialScopedSymbol,
243    ) -> Self {
244        Self {
245            symbol: graph[value.symbol].to_string(),
246            scopes: value.scopes.into_option().map(|scopes| {
247                PartialScopeStack::from_partial_scope_stack(graph, partials, &scopes)
248            }),
249        }
250    }
251
252    pub fn to_partial_scoped_symbol(
253        &self,
254        graph: &mut crate::graph::StackGraph,
255        partials: &mut crate::partial::PartialPaths,
256    ) -> Result<crate::partial::PartialScopedSymbol, Error> {
257        Ok(crate::partial::PartialScopedSymbol {
258            symbol: graph.add_symbol(&self.symbol),
259            scopes: self
260                .scopes
261                .as_ref()
262                .map(|scopes| scopes.to_partial_scope_stack(graph, partials))
263                .transpose()?
264                .into(),
265        })
266    }
267}
268
269#[derive(Clone, Debug, Eq, PartialEq)]
270#[cfg_attr(
271    feature = "serde",
272    derive(serde::Deserialize, serde::Serialize),
273    serde(transparent)
274)]
275#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
276pub struct PartialPathEdgeList {
277    pub(crate) edges: Vec<PartialPathEdge>,
278}
279
280impl PartialPathEdgeList {
281    pub fn from_partial_path_edge_list(
282        graph: &crate::graph::StackGraph,
283        partials: &mut PartialPaths,
284        value: &crate::partial::PartialPathEdgeList,
285    ) -> Self {
286        let mut value = *value;
287        let mut edges = Vec::new();
288        while let Some(edge) = value.pop_front(partials) {
289            edges.push(PartialPathEdge::from_partial_path_edge(
290                graph, partials, &edge,
291            ));
292        }
293        Self { edges }
294    }
295
296    pub fn to_partial_path_edge_list(
297        &self,
298        graph: &mut crate::graph::StackGraph,
299        partials: &mut PartialPaths,
300    ) -> Result<crate::partial::PartialPathEdgeList, Error> {
301        let mut value = crate::partial::PartialPathEdgeList::empty();
302        for edge in &self.edges {
303            let edge = edge.to_partial_path_edge(graph, partials)?;
304            value.push_back(partials, edge);
305        }
306        Ok(value)
307    }
308}
309
310#[derive(Clone, Debug, Eq, PartialEq)]
311#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
312#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
313pub struct PartialPathEdge {
314    pub(crate) source: NodeID,
315    precedence: i32,
316}
317
318impl PartialPathEdge {
319    pub fn from_partial_path_edge(
320        graph: &crate::graph::StackGraph,
321        _partials: &mut PartialPaths,
322        value: &crate::partial::PartialPathEdge,
323    ) -> Self {
324        Self {
325            source: NodeID::from_node_id(graph, value.source_node_id),
326            precedence: value.precedence,
327        }
328    }
329
330    pub fn to_partial_path_edge(
331        &self,
332        graph: &mut crate::graph::StackGraph,
333        _partials: &mut PartialPaths,
334    ) -> Result<crate::partial::PartialPathEdge, Error> {
335        Ok(crate::partial::PartialPathEdge {
336            source_node_id: self.source.to_node_id(graph)?,
337            precedence: self.precedence,
338        })
339    }
340}