molecule_codegen/ast/verified/
mod.rs

1use 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}