gbf_core/decompiler/ast/
ptr.rs

1// This file is based on Rust's implementation of `P<T>`.
2// Original code from Rust is licensed under MIT and Apache 2.0.
3// Copyright (c) The Rust Project Developers
4// Source: https://github.com/rust-lang/rust/blob/master/compiler/rustc_ast/src/ptr.rs
5// Licensed under either the MIT license (https://opensource.org/licenses/MIT)
6// or Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0), at your choice.
7// See https://www.rust-lang.org/policies/licenses for more information.
8
9// The main modifications we do for GBF is replacing the serialization and deserialization
10// with serde's `Serialize` and `Deserialize` traits.
11
12//! The AST pointer.
13//!
14//! Provides [`P<T>`][struct@P], an owned smart pointer.
15//!
16//! # Motivations and benefits
17//!
18//! * **Identity**: sharing AST nodes is problematic for the various analysis
19//!   passes (e.g., one may be able to bypass the borrow checker with a shared
20//!   `ExprKind::AddrOf` node taking a mutable borrow).
21//!
22//! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
23//!   the latter even when the input and output types differ (as it would be the
24//!   case with arenas or a GADT AST using type parameters to toggle features).
25//!
26//! * **Maintainability**: `P<T>` provides an interface, which can remain fully
27//!   functional even if the implementation changes (using a special thread-local
28//!   heap, for example). Moreover, a switch to, e.g., `P<'a, T>` would be easy
29//!   and mostly automated.
30
31use std::fmt::{self, Debug, Display};
32use std::ops::{Deref, DerefMut};
33use std::{slice, vec};
34
35use serde::{Deserialize, Serialize};
36
37use super::meta::Metadata;
38use super::node_id::NodeId;
39
40/// An owned smart pointer.
41///
42/// See the [module level documentation][crate::ptr] for details.
43#[derive(Serialize, Deserialize)]
44pub struct P<T: ?Sized> {
45    ptr: Box<T>,
46    node_id: NodeId,
47    metadata: Metadata,
48}
49
50/// Construct a `P<T>` from a `T` value.
51#[allow(non_snake_case)]
52pub fn P<T: 'static>(value: T) -> P<T> {
53    P {
54        ptr: Box::new(value),
55        node_id: NodeId::new(),
56        metadata: Metadata::default(),
57    }
58}
59
60impl<T: 'static> P<T> {
61    /// Move out of the pointer.
62    /// Intended for chaining transformations not covered by `map`.
63    pub fn and_then<U, F>(self, f: F) -> U
64    where
65        F: FnOnce(T) -> U,
66    {
67        f(*self.ptr)
68    }
69
70    /// Equivalent to `and_then(|x| x)`.
71    pub fn into_inner(self) -> T {
72        *self.ptr
73    }
74
75    /// Produce a new `P<T>` from `self` without reallocating.
76    pub fn map<F>(mut self, f: F) -> P<T>
77    where
78        F: FnOnce(T) -> T,
79    {
80        let x = f(*self.ptr);
81        *self.ptr = x;
82
83        self
84    }
85
86    /// Optionally produce a new `P<T>` from `self` without reallocating.
87    pub fn filter_map<F>(mut self, f: F) -> Option<P<T>>
88    where
89        F: FnOnce(T) -> Option<T>,
90    {
91        *self.ptr = f(*self.ptr)?;
92        Some(self)
93    }
94
95    /// Gets the NodeId
96    pub fn node_id(&self) -> NodeId {
97        self.node_id
98    }
99
100    /// Gets the metadata
101    pub fn metadata(&self) -> &Metadata {
102        &self.metadata
103    }
104
105    /// Gets the metadata mutably
106    pub fn metadata_mut(&mut self) -> &mut Metadata {
107        &mut self.metadata
108    }
109}
110
111impl<T: ?Sized> Deref for P<T> {
112    type Target = T;
113
114    fn deref(&self) -> &T {
115        &self.ptr
116    }
117}
118
119impl<T: ?Sized> DerefMut for P<T> {
120    fn deref_mut(&mut self) -> &mut T {
121        &mut self.ptr
122    }
123}
124
125impl<T: ?Sized> AsRef<T> for P<T> {
126    /// Consumes the `P<T>` and returns the inner `Box<T>`.
127    fn as_ref(&self) -> &T {
128        &self.ptr
129    }
130}
131
132impl<T: 'static + Clone> Clone for P<T> {
133    fn clone(&self) -> P<T> {
134        P {
135            ptr: self.ptr.clone(),
136            // TODO: Should we clone the node_id?
137            node_id: NodeId::new(),
138            metadata: self.metadata.clone(),
139        }
140    }
141}
142
143impl<T: ?Sized + Debug> Debug for P<T> {
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        Debug::fmt(&self.ptr, f)
146    }
147}
148
149impl<T: Display> Display for P<T> {
150    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151        Display::fmt(&**self, f)
152    }
153}
154
155impl<T> fmt::Pointer for P<T> {
156    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157        fmt::Pointer::fmt(&self.ptr, f)
158    }
159}
160
161impl<T> From<T> for P<T> {
162    fn from(value: T) -> Self {
163        P {
164            ptr: Box::new(value),
165            node_id: NodeId::new(),
166            metadata: Metadata::default(),
167        }
168    }
169}
170
171impl<T> P<[T]> {
172    /// Creates a new empty `P<[T]>`.
173    pub fn new() -> P<[T]> {
174        P {
175            ptr: Box::default(),
176            node_id: NodeId::new(),
177            metadata: Metadata::default(),
178        }
179    }
180
181    #[inline(never)]
182    /// Creates a new `P<[T]>` from a `Vec<T>`.
183    pub fn from_vec(v: Vec<T>) -> P<[T]> {
184        P {
185            ptr: v.into_boxed_slice(),
186            node_id: NodeId::new(),
187            metadata: Metadata::default(),
188        }
189    }
190
191    #[inline(never)]
192    /// Converts the `P<[T]>` into a `Vec<T>`.
193    pub fn into_vec(self) -> Vec<T> {
194        self.ptr.into_vec()
195    }
196}
197
198impl<T> Default for P<[T]> {
199    /// Creates an empty `P<[T]>`.
200    fn default() -> P<[T]> {
201        P::new()
202    }
203}
204
205impl<T: Clone> Clone for P<[T]> {
206    fn clone(&self) -> P<[T]> {
207        P::from_vec(self.to_vec())
208    }
209}
210
211impl<T> From<Vec<T>> for P<[T]> {
212    fn from(v: Vec<T>) -> Self {
213        P::from_vec(v)
214    }
215}
216
217impl<T> From<P<[T]>> for Vec<T> {
218    fn from(val: P<[T]>) -> Self {
219        val.into_vec()
220    }
221}
222
223impl<T> FromIterator<T> for P<[T]> {
224    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> P<[T]> {
225        P::from_vec(iter.into_iter().collect())
226    }
227}
228
229impl<T> IntoIterator for P<[T]> {
230    type Item = T;
231    type IntoIter = vec::IntoIter<T>;
232
233    fn into_iter(self) -> Self::IntoIter {
234        self.into_vec().into_iter()
235    }
236}
237
238impl<'a, T> IntoIterator for &'a P<[T]> {
239    type Item = &'a T;
240    type IntoIter = slice::Iter<'a, T>;
241    fn into_iter(self) -> Self::IntoIter {
242        self.ptr.iter()
243    }
244}
245
246impl<T: PartialEq> PartialEq for P<T> {
247    fn eq(&self, other: &Self) -> bool {
248        **self == **other
249    }
250}
251
252impl<T: Eq> Eq for P<T> {}