go_parser/
objects.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5use super::ast;
6use super::scope;
7use std::marker::PhantomData;
8use std::ops::Index;
9use std::ops::IndexMut;
10
11#[cfg(feature = "serde_borsh")]
12use borsh::{maybestd::io::Result, maybestd::io::Write, BorshDeserialize, BorshSerialize};
13
14pub trait PiggyVecKey {
15    fn as_usize(&self) -> usize;
16}
17
18/// A vec that you can only insert into, so that the index can be used as a key
19///
20#[derive(Debug)]
21pub struct PiggyVec<K, V>
22where
23    K: PiggyVecKey + From<usize>,
24{
25    vec: Vec<V>,
26    phantom: PhantomData<K>,
27}
28
29impl<K, V> PiggyVec<K, V>
30where
31    K: PiggyVecKey + From<usize>,
32{
33    pub fn with_capacity(capacity: usize) -> Self {
34        Self {
35            vec: Vec::with_capacity(capacity),
36            phantom: PhantomData {},
37        }
38    }
39
40    #[inline]
41    pub fn insert(&mut self, v: V) -> K {
42        self.vec.push(v);
43        (self.vec.len() - 1).into()
44    }
45
46    #[inline]
47    pub fn vec(&self) -> &Vec<V> {
48        &self.vec
49    }
50
51    pub fn iter<'a>(&'a self) -> PiggyVecIter<'a, K, V> {
52        PiggyVecIter {
53            vec_iter: self.vec.iter(),
54            phantom: PhantomData {},
55        }
56    }
57}
58
59impl<K, V> Index<K> for PiggyVec<K, V>
60where
61    K: PiggyVecKey + From<usize>,
62{
63    type Output = V;
64
65    #[inline]
66    fn index(&self, index: K) -> &Self::Output {
67        &self.vec[index.as_usize()]
68    }
69}
70
71impl<K, V> IndexMut<K> for PiggyVec<K, V>
72where
73    K: PiggyVecKey + From<usize>,
74{
75    #[inline]
76    fn index_mut(&mut self, index: K) -> &mut Self::Output {
77        &mut self.vec[index.as_usize()]
78    }
79}
80
81impl<K, V> From<Vec<V>> for PiggyVec<K, V>
82where
83    K: PiggyVecKey + From<usize>,
84{
85    #[inline]
86    fn from(vec: Vec<V>) -> Self {
87        PiggyVec {
88            vec,
89            phantom: PhantomData {},
90        }
91    }
92}
93
94#[cfg(feature = "serde_borsh")]
95impl<K, V> BorshSerialize for PiggyVec<K, V>
96where
97    K: PiggyVecKey + From<usize>,
98    V: BorshSerialize,
99{
100    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
101        self.vec().serialize(writer)
102    }
103}
104
105#[cfg(feature = "serde_borsh")]
106impl<K, V> BorshDeserialize for PiggyVec<K, V>
107where
108    K: PiggyVecKey + From<usize>,
109    V: BorshDeserialize,
110{
111    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> Result<Self> {
112        Ok(Vec::<V>::deserialize_reader(reader)?.into())
113    }
114}
115
116pub struct PiggyVecIter<'a, K, V>
117where
118    K: PiggyVecKey + From<usize>,
119{
120    vec_iter: std::slice::Iter<'a, V>,
121    phantom: PhantomData<K>,
122}
123
124impl<'a, K, V> Iterator for PiggyVecIter<'a, K, V>
125where
126    K: PiggyVecKey + From<usize>,
127{
128    type Item = &'a V;
129
130    fn next(&mut self) -> Option<Self::Item> {
131        self.vec_iter.next()
132    }
133}
134
135#[macro_export]
136macro_rules! piggy_key_type {
137    ( $(#[$outer:meta])* $vis:vis struct $name:ident; $($rest:tt)* ) => {
138        $(#[$outer])*
139        #[derive(Copy, Clone, Default,
140                 Eq, PartialEq, Ord, PartialOrd,
141                 Hash, Debug)]
142        #[repr(transparent)]
143        $vis struct $name(usize);
144
145        impl $name {
146            #[inline]
147            pub fn null() -> Self {
148                $name(std::usize::MAX)
149            }
150        }
151
152        impl From<usize> for $name {
153            #[inline]
154            fn from(k: usize) -> Self {
155                $name(k)
156            }
157        }
158
159        impl $crate::PiggyVecKey for $name {
160            #[inline]
161            fn as_usize(&self) -> usize {
162                self.0
163            }
164        }
165
166        piggy_key_type!($($rest)*);
167    };
168
169    () => {}
170}
171
172piggy_key_type! {
173    pub struct LabeledStmtKey;
174    pub struct AssignStmtKey;
175    pub struct SpecKey;
176    pub struct FuncDeclKey;
177    pub struct FuncTypeKey;
178    pub struct IdentKey;
179    pub struct FieldKey;
180    pub struct EntityKey;
181    pub struct ScopeKey;
182}
183
184pub type LabeledStmts = PiggyVec<LabeledStmtKey, ast::LabeledStmt>;
185pub type AssignStmts = PiggyVec<AssignStmtKey, ast::AssignStmt>;
186pub type Specs = PiggyVec<SpecKey, ast::Spec>;
187pub type FuncDecls = PiggyVec<FuncDeclKey, ast::FuncDecl>;
188pub type FuncTypes = PiggyVec<FuncTypeKey, ast::FuncType>;
189pub type Idents = PiggyVec<IdentKey, ast::Ident>;
190pub type Fields = PiggyVec<FieldKey, ast::Field>;
191pub type Entitys = PiggyVec<EntityKey, scope::Entity>;
192pub type Scopes = PiggyVec<ScopeKey, scope::Scope>;
193
194pub struct AstObjects {
195    pub l_stmts: LabeledStmts,
196    pub a_stmts: AssignStmts,
197    pub specs: Specs,
198    pub fdecls: FuncDecls,
199    pub ftypes: FuncTypes,
200    pub idents: Idents,
201    pub fields: Fields,
202    pub entities: Entitys,
203    pub scopes: Scopes,
204}
205
206impl AstObjects {
207    pub fn new() -> AstObjects {
208        const CAP: usize = 16;
209        AstObjects {
210            l_stmts: PiggyVec::with_capacity(CAP),
211            a_stmts: PiggyVec::with_capacity(CAP),
212            specs: PiggyVec::with_capacity(CAP),
213            fdecls: PiggyVec::with_capacity(CAP),
214            ftypes: PiggyVec::with_capacity(CAP),
215            idents: PiggyVec::with_capacity(CAP),
216            fields: PiggyVec::with_capacity(CAP),
217            entities: PiggyVec::with_capacity(CAP),
218            scopes: PiggyVec::with_capacity(CAP),
219        }
220    }
221}