molecule_codegen/ast/verified/
mod.rs1use std::{collections::HashMap, rc::Rc};
2
3use property::Property;
4
5mod complete;
6mod default_content;
7mod has_name;
8
9#[cfg(feature = "compiler-plugin")]
10mod recover;
11
12pub use default_content::DefaultContent;
13pub use has_name::HasName;
14
15use crate::ast::SyntaxVersion;
16
17type Deps<'a> = HashMap<&'a str, Rc<super::TopDecl>>;
18
19#[derive(Debug, Property)]
20#[property(get(public))]
21pub struct Ast {
22 syntax_version: SyntaxVersion,
23 namespace: String,
24 imports: Vec<ImportStmt>,
25 decls: Vec<Rc<TopDecl>>,
26}
27
28#[derive(Debug, Clone, Property)]
29#[property(get(public))]
30pub struct ImportStmt {
31 name: String,
32 paths: Vec<String>,
33 path_supers: usize,
34}
35
36#[derive(Debug)]
37pub enum TopDecl {
38 Primitive(Primitive),
39 Option_(Option_),
40 Union(Union),
41 Array(Array),
42 Struct(Struct),
43 FixVec(FixVec),
44 DynVec(DynVec),
45 Table(Table),
46}
47
48#[derive(Debug, Property)]
49#[property(get(public))]
50pub struct Primitive {
51 name: String,
52 size: usize,
53}
54
55#[derive(Debug, Property)]
56#[property(get(public))]
57pub struct Option_ {
58 name: String,
59 item: ItemDecl,
60 imported_depth: usize,
61}
62
63#[derive(Debug, Property)]
64#[property(get(public))]
65pub struct Union {
66 name: String,
67 items: Vec<UnionItemDecl>,
68 imported_depth: usize,
69}
70
71#[derive(Debug, Property)]
72#[property(get(public))]
73pub struct Array {
74 name: String,
75 item: ItemDecl,
76 item_count: usize,
77 imported_depth: usize,
78 item_size: usize,
79}
80
81#[derive(Debug, Property)]
82#[property(get(public))]
83pub struct Struct {
84 name: String,
85 fields: Vec<FieldDecl>,
86 imported_depth: usize,
87 field_sizes: Vec<usize>,
88}
89
90#[derive(Debug, Property)]
91#[property(get(public))]
92pub struct FixVec {
93 name: String,
94 item: ItemDecl,
95 imported_depth: usize,
96 item_size: usize,
97}
98
99#[derive(Debug, Property)]
100#[property(get(public))]
101pub struct DynVec {
102 name: String,
103 item: ItemDecl,
104 imported_depth: usize,
105}
106
107#[derive(Debug, Property)]
108#[property(get(public))]
109pub struct Table {
110 name: String,
111 fields: Vec<FieldDecl>,
112 imported_depth: usize,
113}
114
115#[derive(Debug, Property)]
116#[property(get(public))]
117pub struct ItemDecl {
118 typ: Rc<TopDecl>,
119}
120
121#[derive(Debug, Property)]
122#[property(get(public))]
123pub struct UnionItemDecl {
124 typ: Rc<TopDecl>,
125 id: usize,
126}
127
128#[derive(Debug, Property)]
129#[property(get(public))]
130pub struct FieldDecl {
131 name: String,
132 typ: Rc<TopDecl>,
133}
134
135impl Ast {
136 pub fn major_decls(&self) -> Vec<Rc<TopDecl>> {
137 self.decls
138 .iter()
139 .filter(|d| d.imported_depth() == 0)
140 .map(Rc::clone)
141 .collect()
142 }
143}
144
145impl TopDecl {
146 fn new_primitive(name: &str) -> Option<Self> {
147 match name {
148 "byte" => Some(Primitive {
149 name: name.to_owned(),
150 size: 1,
151 }),
152 _ => None,
153 }
154 .map(Self::Primitive)
155 }
156
157 pub fn is_byte(&self) -> bool {
158 if let Self::Primitive(inner) = self {
159 inner.size == 1
160 } else {
161 false
162 }
163 }
164
165 fn imported_depth(&self) -> usize {
166 match self {
167 Self::Primitive(_) => usize::max_value(),
168 Self::Option_(inner) => inner.imported_depth,
169 Self::Union(inner) => inner.imported_depth,
170 Self::Array(inner) => inner.imported_depth,
171 Self::Struct(inner) => inner.imported_depth,
172 Self::FixVec(inner) => inner.imported_depth,
173 Self::DynVec(inner) => inner.imported_depth,
174 Self::Table(inner) => inner.imported_depth,
175 }
176 }
177
178 fn total_size(&self) -> Option<usize> {
179 match self {
180 Self::Primitive(inner) => Some(inner.size),
181 Self::Option_(_) => None,
182 Self::Union(_) => None,
183 Self::Array(inner) => Some(inner.total_size()),
184 Self::Struct(inner) => Some(inner.total_size()),
185 Self::FixVec(_) => None,
186 Self::DynVec(_) => None,
187 Self::Table(_) => None,
188 }
189 }
190}
191
192impl Array {
193 pub fn total_size(&self) -> usize {
194 self.item_size() * self.item_count()
195 }
196}
197
198impl Struct {
199 pub fn total_size(&self) -> usize {
200 self.field_sizes().iter().sum::<usize>()
201 }
202}
203
204macro_rules! impl_into_top_decl_for {
205 ($type:ident) => {
206 impl From<$type> for TopDecl {
207 fn from(typ: $type) -> Self {
208 TopDecl::$type(typ)
209 }
210 }
211 };
212}
213
214impl_into_top_decl_for!(Primitive);
215impl_into_top_decl_for!(Option_);
216impl_into_top_decl_for!(Union);
217impl_into_top_decl_for!(Array);
218impl_into_top_decl_for!(Struct);
219impl_into_top_decl_for!(FixVec);
220impl_into_top_decl_for!(DynVec);
221impl_into_top_decl_for!(Table);
222
223impl ItemDecl {
224 fn new(top_decl: &Rc<TopDecl>) -> Self {
225 Self {
226 typ: Rc::clone(top_decl),
227 }
228 }
229}
230
231impl UnionItemDecl {
232 fn new(top_decl: &Rc<TopDecl>, customize_id: usize) -> Self {
233 Self {
234 typ: Rc::clone(top_decl),
235 id: customize_id,
236 }
237 }
238}
239
240impl FieldDecl {
241 fn new(name: &str, top_decl: &Rc<TopDecl>) -> Self {
242 Self {
243 name: name.to_owned(),
244 typ: Rc::clone(top_decl),
245 }
246 }
247}