Skip to content

Commit b7190db

Browse files
Improve generation
Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
1 parent 3c631e9 commit b7190db

File tree

5 files changed

+1685
-640
lines changed

5 files changed

+1685
-640
lines changed

crates/generators/codegen-core/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use blueberry_ast::{
22
Annotation, AnnotationParam, Commented, ConstValue, Definition, MessageDef, Type,
33
};
44

5+
pub mod type_registry;
6+
pub use type_registry::{ResolvedMember, TypeRegistry, map_builtin_ident};
7+
58
pub const DEFAULT_MODULE_KEY: u16 = 0x4242;
69
pub const MESSAGE_HEADER_SIZE: usize = 8;
710

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
use std::collections::{HashMap, HashSet};
2+
3+
use blueberry_ast::{Definition, MessageDef, StructDef, Type};
4+
5+
#[derive(Clone)]
6+
pub struct TypedefInfo {
7+
pub ty: Type,
8+
pub scope: Vec<String>,
9+
}
10+
11+
#[derive(Clone)]
12+
pub struct StructInfo {
13+
pub def: StructDef,
14+
pub scope: Vec<String>,
15+
}
16+
17+
#[derive(Clone)]
18+
pub struct MessageInfo {
19+
pub def: MessageDef,
20+
pub scope: Vec<String>,
21+
}
22+
23+
#[derive(Clone)]
24+
pub struct ResolvedMember {
25+
pub name: String,
26+
pub ty: Type,
27+
pub comments: Vec<String>,
28+
}
29+
30+
#[derive(Default)]
31+
pub struct TypeRegistry {
32+
typedefs: HashMap<Vec<String>, TypedefInfo>,
33+
structs: HashMap<Vec<String>, StructInfo>,
34+
messages: HashMap<Vec<String>, MessageInfo>,
35+
enums: HashMap<Vec<String>, Type>,
36+
}
37+
38+
impl TypeRegistry {
39+
pub fn new(definitions: &[Definition]) -> Self {
40+
let mut registry = TypeRegistry::default();
41+
let mut scope = Vec::new();
42+
registry.collect(definitions, &mut scope);
43+
registry
44+
}
45+
46+
pub fn resolve_type(&self, ty: &Type, scope: &[String]) -> Type {
47+
match ty {
48+
Type::Sequence { element_type, size } => Type::Sequence {
49+
element_type: Box::new(self.resolve_type(element_type, scope)),
50+
size: *size,
51+
},
52+
Type::Array {
53+
element_type,
54+
dimensions,
55+
} => {
56+
let mut resolved = self.resolve_type(element_type, scope);
57+
for &dim in dimensions.iter().rev() {
58+
resolved = Type::Sequence {
59+
element_type: Box::new(resolved),
60+
size: Some(dim),
61+
};
62+
}
63+
resolved
64+
}
65+
Type::ScopedName(name) => {
66+
if let [single] = name.as_slice()
67+
&& let Some(mapped) = map_builtin_ident(single)
68+
{
69+
return mapped;
70+
}
71+
if let Some(path) = self.resolve_typedef(name, scope) {
72+
let info = self.typedefs.get(&path).expect("typedef info missing");
73+
self.resolve_type(&info.ty, &info.scope)
74+
} else if let Some(path) = self.resolve_struct(name, scope) {
75+
Type::ScopedName(path)
76+
} else if let Some(path) = self.resolve_message(name, scope) {
77+
Type::ScopedName(path)
78+
} else if let Some(path) = self.resolve_enum(name, scope) {
79+
Type::ScopedName(path)
80+
} else {
81+
Type::ScopedName(name.clone())
82+
}
83+
}
84+
other => other.clone(),
85+
}
86+
}
87+
88+
pub fn collect_struct_members(&self, path: &[String]) -> Vec<ResolvedMember> {
89+
let info = self
90+
.structs
91+
.get(path)
92+
.unwrap_or_else(|| panic!("missing struct {:?}", path));
93+
let mut members = Vec::new();
94+
if let Some(base) = &info.def.base
95+
&& let Some(base_path) = self.resolve_struct(base, &info.scope)
96+
{
97+
members.extend(self.collect_struct_members(&base_path));
98+
}
99+
for member in &info.def.members {
100+
let ty = self.resolve_type(&member.node.type_, &info.scope);
101+
members.push(ResolvedMember {
102+
name: member.node.name.clone(),
103+
ty,
104+
comments: member.comments.clone(),
105+
});
106+
}
107+
members
108+
}
109+
110+
pub fn collect_message_members(&self, path: &[String]) -> Vec<ResolvedMember> {
111+
let info = self
112+
.messages
113+
.get(path)
114+
.unwrap_or_else(|| panic!("missing message {:?}", path));
115+
let mut members = Vec::new();
116+
if let Some(base) = &info.def.base
117+
&& let Some(base_path) = self.resolve_message(base, &info.scope)
118+
{
119+
members.extend(self.collect_message_members(&base_path));
120+
}
121+
for member in &info.def.members {
122+
let ty = self.resolve_type(&member.node.type_, &info.scope);
123+
members.push(ResolvedMember {
124+
name: member.node.name.clone(),
125+
ty,
126+
comments: member.comments.clone(),
127+
});
128+
}
129+
members
130+
}
131+
132+
pub fn struct_paths(&self) -> Vec<Vec<String>> {
133+
self.structs.keys().cloned().collect()
134+
}
135+
136+
pub fn enum_base(&self, path: &[String]) -> Option<&Type> {
137+
self.enums.get(path)
138+
}
139+
140+
pub fn resolve_typedef(&self, name: &[String], scope: &[String]) -> Option<Vec<String>> {
141+
self.resolve_path(name, scope, self.typedefs.keys())
142+
}
143+
144+
pub fn resolve_struct(&self, name: &[String], scope: &[String]) -> Option<Vec<String>> {
145+
self.resolve_path(name, scope, self.structs.keys())
146+
}
147+
148+
pub fn resolve_message(&self, name: &[String], scope: &[String]) -> Option<Vec<String>> {
149+
self.resolve_path(name, scope, self.messages.keys())
150+
}
151+
152+
pub fn resolve_enum(&self, name: &[String], scope: &[String]) -> Option<Vec<String>> {
153+
self.resolve_path(name, scope, self.enums.keys())
154+
}
155+
156+
fn collect(&mut self, defs: &[Definition], scope: &mut Vec<String>) {
157+
for def in defs {
158+
match def {
159+
Definition::ModuleDef(module) => {
160+
scope.push(module.node.name.clone());
161+
self.collect(&module.node.definitions, scope);
162+
scope.pop();
163+
}
164+
Definition::TypeDef(typedef) => {
165+
let mut path = scope.clone();
166+
path.push(typedef.node.name.clone());
167+
self.typedefs.insert(
168+
path,
169+
TypedefInfo {
170+
ty: typedef.node.base_type.clone(),
171+
scope: scope.clone(),
172+
},
173+
);
174+
}
175+
Definition::StructDef(struct_def) => {
176+
let mut path = scope.clone();
177+
path.push(struct_def.node.name.clone());
178+
self.structs.insert(
179+
path,
180+
StructInfo {
181+
def: struct_def.node.clone(),
182+
scope: scope.clone(),
183+
},
184+
);
185+
}
186+
Definition::MessageDef(message_def) => {
187+
let mut path = scope.clone();
188+
path.push(message_def.node.name.clone());
189+
self.messages.insert(
190+
path,
191+
MessageInfo {
192+
def: message_def.node.clone(),
193+
scope: scope.clone(),
194+
},
195+
);
196+
}
197+
Definition::EnumDef(enum_def) => {
198+
let mut path = scope.clone();
199+
path.push(enum_def.node.name.clone());
200+
let repr = enum_def
201+
.node
202+
.base_type
203+
.clone()
204+
.unwrap_or(Type::UnsignedLong);
205+
self.enums.insert(path, repr);
206+
}
207+
Definition::ConstDef(_) | Definition::ImportDef(_) => {}
208+
}
209+
}
210+
}
211+
212+
fn resolve_path<'a, I>(
213+
&self,
214+
name: &[String],
215+
scope: &[String],
216+
entries: I,
217+
) -> Option<Vec<String>>
218+
where
219+
I: IntoIterator<Item = &'a Vec<String>>,
220+
{
221+
let paths: Vec<Vec<String>> = entries.into_iter().cloned().collect();
222+
let lookup: HashSet<Vec<String>> = paths.iter().cloned().collect();
223+
for prefix in (0..=scope.len()).rev() {
224+
let mut candidate = scope[..prefix].to_vec();
225+
candidate.extend_from_slice(name);
226+
if lookup.contains(&candidate) {
227+
return Some(candidate);
228+
}
229+
}
230+
self.resolve_by_suffix(name, &paths)
231+
}
232+
233+
fn resolve_by_suffix(&self, name: &[String], paths: &[Vec<String>]) -> Option<Vec<String>> {
234+
let matches: Vec<&Vec<String>> = paths.iter().filter(|path| path.ends_with(name)).collect();
235+
if matches.len() == 1 {
236+
return Some(matches[0].clone());
237+
}
238+
None
239+
}
240+
}
241+
242+
pub fn map_builtin_ident(name: &str) -> Option<Type> {
243+
match name {
244+
"int8" => Some(Type::Octet),
245+
"int16" => Some(Type::Short),
246+
"int32" => Some(Type::Long),
247+
"int64" => Some(Type::LongLong),
248+
"uint8" => Some(Type::Octet),
249+
"uint16" => Some(Type::UnsignedShort),
250+
"uint32" => Some(Type::UnsignedLong),
251+
"uint64" => Some(Type::UnsignedLongLong),
252+
_ => None,
253+
}
254+
}

0 commit comments

Comments
 (0)