1use solar_data_structures::{index::IndexSlice, newtype_index, BumpExt};
4use std::fmt;
5
6pub use crate::token::CommentKind;
7pub use solar_interface::{Ident, Span, Symbol};
8
9mod expr;
10pub use expr::*;
11
12mod item;
13pub use item::*;
14
15mod lit;
16pub use lit::*;
17
18mod path;
19pub use path::*;
20
21mod semver;
22pub use semver::*;
23
24mod stmt;
25pub use stmt::*;
26
27mod ty;
28pub use ty::*;
29
30pub mod yul;
31
32pub type Box<'ast, T> = &'ast mut T;
33
34pub struct Arena {
36 pub bump: bumpalo::Bump,
37 pub literals: typed_arena::Arena<Lit>,
38}
39
40impl Arena {
41 pub fn new() -> Self {
43 Self { bump: bumpalo::Bump::new(), literals: typed_arena::Arena::new() }
44 }
45
46 pub fn allocated_bytes(&self) -> usize {
47 self.bump.allocated_bytes()
48 + (self.literals.len() + self.literals.uninitialized_array().len())
49 * std::mem::size_of::<Lit>()
50 }
51
52 pub fn used_bytes(&self) -> usize {
53 self.bump.used_bytes() + self.literals.len() * std::mem::size_of::<Lit>()
54 }
55}
56
57impl Default for Arena {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl std::ops::Deref for Arena {
64 type Target = bumpalo::Bump;
65
66 #[inline]
67 fn deref(&self) -> &Self::Target {
68 &self.bump
69 }
70}
71
72#[derive(Default)]
74pub struct DocComments<'ast>(pub Box<'ast, [DocComment]>);
75
76impl<'ast> std::ops::Deref for DocComments<'ast> {
77 type Target = Box<'ast, [DocComment]>;
78
79 #[inline]
80 fn deref(&self) -> &Self::Target {
81 &self.0
82 }
83}
84
85impl std::ops::DerefMut for DocComments<'_> {
86 #[inline]
87 fn deref_mut(&mut self) -> &mut Self::Target {
88 &mut self.0
89 }
90}
91
92impl<'ast> From<Box<'ast, [DocComment]>> for DocComments<'ast> {
93 fn from(comments: Box<'ast, [DocComment]>) -> Self {
94 Self(comments)
95 }
96}
97
98impl fmt::Debug for DocComments<'_> {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 f.write_str("DocComments ")?;
101 self.0.fmt(f)
102 }
103}
104
105impl DocComments<'_> {
106 pub fn span(&self) -> Span {
108 Span::join_first_last(self.iter().map(|d| d.span))
109 }
110}
111
112#[derive(Clone, Copy, Debug)]
114pub struct DocComment {
115 pub kind: CommentKind,
117 pub span: Span,
119 pub symbol: Symbol,
122}
123
124pub struct SourceUnit<'ast> {
126 pub items: Box<'ast, IndexSlice<ItemId, [Item<'ast>]>>,
128}
129
130impl fmt::Debug for SourceUnit<'_> {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.write_str("SourceUnit ")?;
133 self.items.fmt(f)
134 }
135}
136
137impl<'ast> SourceUnit<'ast> {
138 pub fn new(items: Box<'ast, [Item<'ast>]>) -> Self {
140 Self { items: IndexSlice::from_slice_mut(items) }
141 }
142}
143
144newtype_index! {
145 pub struct ItemId;
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
154 fn no_drop() {
155 #[track_caller]
156 fn assert_no_drop<T>() {
157 assert!(!std::mem::needs_drop::<T>(), "{}", std::any::type_name::<T>());
158 }
159 assert_no_drop::<Type<'_>>();
160 assert_no_drop::<Expr<'_>>();
161 assert_no_drop::<Stmt<'_>>();
162 assert_no_drop::<Item<'_>>();
163 assert_no_drop::<SourceUnit<'_>>();
164 }
165}