1use planus_types::{
2 ast::Docstrings,
3 intermediate::{
4 AbsolutePath, DeclarationIndex, DeclarationKind, Declarations, NamespaceIndex, SimpleType,
5 Table, Type, TypeKind,
6 },
7};
8use vec_map::VecMap;
9
10use super::backend::{
11 Backend, DeclarationNames, DeclarationTranslationContext, NamespaceNames, ResolvedType,
12};
13use crate::backend::{DeclInfo, Keywords, Names, RelativeNamespace};
14
15#[derive(Debug, Clone)]
16pub struct BackendNamespace<B: ?Sized + Backend> {
17 pub info: B::NamespaceInfo,
18 pub children: Vec<BackendNamespace<B>>,
19 pub declarations: Vec<BackendDeclaration<B>>,
20 pub docstrings: Docstrings,
21}
22
23#[derive(Debug, Clone)]
24pub enum BackendDeclaration<B: ?Sized + Backend> {
25 Table(BackendTable<B>),
26 Struct(BackendStruct<B>),
27 Enum(BackendEnum<B>),
28 Union(BackendUnion<B>),
29 #[allow(dead_code)]
30 RpcService(BackendRpcService<B>),
31}
32
33#[derive(Debug, Clone)]
34pub struct BackendTable<B: ?Sized + Backend> {
35 pub docstrings: Docstrings,
36 pub max_vtable_size: u32,
37 pub _max_size: u32,
38 pub _max_alignment: u32,
39 pub info: B::TableInfo,
40 pub fields: BackendTableFields<B::TableFieldInfo>,
41}
42
43#[derive(Debug, Clone)]
44pub struct BackendStruct<B: ?Sized + Backend> {
45 pub docstrings: Docstrings,
46 pub size: u32,
47 pub alignment: u32,
48 pub info: B::StructInfo,
49 pub fields: Vec<BackendStructField<B::StructFieldInfo>>,
50}
51
52#[derive(Debug, Clone)]
53pub struct BackendEnum<B: ?Sized + Backend> {
54 pub docstrings: Docstrings,
55 pub size: u32,
56 pub info: B::EnumInfo,
57 pub variants: Vec<BackendVariant<B::EnumVariantInfo>>,
58}
59
60#[derive(Debug, Clone)]
61pub struct BackendUnion<B: ?Sized + Backend> {
62 pub docstrings: Docstrings,
63 pub info: B::UnionInfo,
64 pub variants: Vec<BackendVariant<B::UnionVariantInfo>>,
65}
66
67#[derive(Debug, Clone)]
68pub struct BackendRpcService<B: ?Sized + Backend> {
69 pub _docstrings: Docstrings,
70 pub _info: B::RpcServiceInfo,
71 pub _methods: Vec<B::RpcMethodInfo>,
72}
73
74#[derive(Debug, Clone)]
75pub struct NameAndDocstrings {
76 pub original_name: String,
77 pub docstrings: Docstrings,
78}
79
80#[derive(Debug, Clone)]
81pub struct BackendVariant<V> {
82 pub name_and_docs: NameAndDocstrings,
83 pub variant: V,
84}
85
86impl<V> std::ops::Deref for BackendVariant<V> {
87 type Target = V;
88
89 fn deref(&self) -> &V {
90 &self.variant
91 }
92}
93#[derive(Debug, Clone)]
94pub struct BackendTableFields<F> {
95 fields: VecMap<(NameAndDocstrings, F)>,
96 declaration_order: Vec<(usize, u32, BackendTableFieldType)>,
97 alignment_order: Vec<(usize, u32, BackendTableFieldType)>,
98}
99
100impl<F> BackendTableFields<F> {
101 #[allow(clippy::too_many_arguments)]
102 fn new<'a, B: ?Sized + Backend<TableFieldInfo = F>>(
103 declarations: &'a Declarations,
104 backend: &mut B,
105 translation_context: &mut DeclarationTranslationContext<'a, '_, B>,
106 full_translated_decls: &'a VecMap<BackendDeclaration<B>>,
107 decl: &'a Table,
108 decl_path: &AbsolutePath,
109 translated_decl: &B::TableInfo,
110 ) -> BackendTableFields<<B as Backend>::TableFieldInfo> {
111 let mut declaration_order = Vec::new();
112
113 let fields = decl
114 .fields
115 .iter()
116 .enumerate()
117 .filter(|(_index, (_field_name, field))| !field.deprecated)
118 .map(|(index, (field_name, field))| {
119 match &field.type_.kind {
120 TypeKind::Union(_) => {
121 declaration_order.push((
122 index,
123 field.vtable_index,
124 BackendTableFieldType::UnionKey,
125 ));
126 declaration_order.push((
127 index,
128 field.vtable_index + 1,
129 BackendTableFieldType::UnionValue,
130 ));
131 }
132 TypeKind::Vector(v) if matches!(v.kind, TypeKind::Union(_)) => {
133 declaration_order.push((
134 index,
135 field.vtable_index,
136 BackendTableFieldType::UnionKeyVector,
137 ));
138 declaration_order.push((
139 index,
140 field.vtable_index + 1,
141 BackendTableFieldType::UnionValueVector,
142 ));
143 }
144 _ => {
145 declaration_order.push((
146 index,
147 field.vtable_index,
148 BackendTableFieldType::Other,
149 ));
150 }
151 }
152
153 let translated_type = translate_type(
154 translation_context,
155 declarations,
156 full_translated_decls,
157 &field.type_,
158 &decl_path.clone_pop(),
159 );
160 (
161 index,
162 (
163 NameAndDocstrings {
164 original_name: field_name.clone(),
165 docstrings: field.docstrings.clone(),
166 },
167 backend.generate_table_field(
168 translation_context,
169 translated_decl,
170 decl,
171 field_name,
172 field,
173 translated_type,
174 ),
175 ),
176 )
177 })
178 .collect();
179
180 let mut alignment_order = declaration_order.clone();
181 alignment_order.sort_by_key(|(index, _, field_type)| {
182 std::cmp::Reverse(if *field_type == BackendTableFieldType::UnionKey {
183 1
184 } else {
185 decl.fields[*index].object_alignment
186 })
187 });
188
189 BackendTableFields {
190 fields,
191 declaration_order,
192 alignment_order,
193 }
194 }
195
196 pub fn declaration_order(&self) -> impl Iterator<Item = BackendTableField<'_, F>> {
197 self.declaration_order
198 .iter()
199 .filter(|(_, _, field_type)| !field_type.is_key())
200 .map(
201 move |&(index, vtable_index, field_type)| BackendTableField {
202 field_type,
203 vtable_index,
204 name_and_docs: &self.fields[index].0,
205 info: &self.fields[index].1,
206 },
207 )
208 }
209
210 pub fn alignment_order(&self) -> impl Iterator<Item = BackendTableField<'_, F>> {
211 self.alignment_order
212 .iter()
213 .map(
214 move |&(index, vtable_index, field_type)| BackendTableField {
215 field_type,
216 vtable_index,
217 name_and_docs: &self.fields[index].0,
218 info: &self.fields[index].1,
219 },
220 )
221 }
222
223 pub fn is_empty(&self) -> bool {
224 self.declaration_order.is_empty()
225 }
226}
227
228impl<F> Default for BackendTableFields<F> {
229 fn default() -> Self {
230 Self {
231 fields: Default::default(),
232 declaration_order: Default::default(),
233 alignment_order: Default::default(),
234 }
235 }
236}
237
238pub struct BackendTableField<'a, F> {
239 pub field_type: BackendTableFieldType,
240 pub vtable_index: u32,
241 pub info: &'a F,
242 pub name_and_docs: &'a NameAndDocstrings,
243}
244
245#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
246pub enum BackendTableFieldType {
247 UnionKey,
248 UnionValue,
249 UnionKeyVector,
250 UnionValueVector,
251 Other,
252}
253
254impl BackendTableFieldType {
255 pub fn is_key(self) -> bool {
256 matches!(self, Self::UnionKey | Self::UnionKeyVector)
257 }
258}
259
260#[derive(Debug, Clone)]
261pub struct BackendStructField<F> {
262 pub offset: u32,
263 pub size: u32,
264 pub padding_after_field: u32,
265 pub info: F,
266 pub name_and_docs: NameAndDocstrings,
267}
268
269fn translate_type_index<'a, B: ?Sized + Backend>(
270 translation_context: &DeclarationTranslationContext<'a, '_, B>,
271 declarations: &'a Declarations,
272 full_translated_decls: &'a VecMap<BackendDeclaration<B>>,
273 index: DeclarationIndex,
274 current_namespace_path: &AbsolutePath,
275) -> ResolvedType<'a, B> {
276 let (path, decl) = &translation_context.translated_decls[index.0];
277 let relative_path: RelativeNamespace<B> = RelativeNamespace::new(
278 current_namespace_path,
279 &path.clone_pop(),
280 translation_context.translated_namespaces,
281 declarations,
282 );
283 match decl {
284 DeclInfo::Table(translated_decl, decl) => {
285 ResolvedType::Table(index, decl, translated_decl, relative_path)
286 }
287 DeclInfo::Struct(translated_decl, decl) => {
288 ResolvedType::Struct(index, decl, translated_decl, relative_path)
289 }
290 DeclInfo::Enum(translated_decl, decl) => {
291 if let BackendDeclaration::Enum(BackendEnum { variants, .. }) =
292 full_translated_decls.get(index.0).unwrap()
293 {
294 ResolvedType::Enum(index, decl, translated_decl, relative_path, variants)
295 } else {
296 unreachable!()
297 }
298 }
299 DeclInfo::Union(translated_decl, decl) => {
300 ResolvedType::Union(index, decl, translated_decl, relative_path)
301 }
302 DeclInfo::RpcService(_translated_decl, _decl) => todo!(),
303 }
304}
305
306fn translate_type<'a, B: ?Sized + Backend>(
307 translation_context: &DeclarationTranslationContext<'a, '_, B>,
308 declarations: &'a Declarations,
309 full_translated_decls: &'a VecMap<BackendDeclaration<B>>,
310 type_: &'a Type,
311 current_namespace_path: &AbsolutePath,
312) -> ResolvedType<'a, B> {
313 match &type_.kind {
314 TypeKind::Table(index)
315 | TypeKind::Union(index)
316 | TypeKind::SimpleType(SimpleType::Struct(index))
317 | TypeKind::SimpleType(SimpleType::Enum(index)) => translate_type_index(
318 translation_context,
319 declarations,
320 full_translated_decls,
321 *index,
322 current_namespace_path,
323 ),
324 TypeKind::SimpleType(type_) => translate_simple_type(
325 translation_context,
326 declarations,
327 full_translated_decls,
328 type_,
329 current_namespace_path,
330 ),
331 TypeKind::Vector(type_) => ResolvedType::Vector(Box::new(translate_type(
332 translation_context,
333 declarations,
334 full_translated_decls,
335 type_,
336 current_namespace_path,
337 ))),
338 TypeKind::Array(type_, size) => ResolvedType::Array(
339 Box::new(translate_type(
340 translation_context,
341 declarations,
342 full_translated_decls,
343 type_,
344 current_namespace_path,
345 )),
346 *size,
347 ),
348 TypeKind::String => ResolvedType::String,
349 }
350}
351
352fn translate_simple_type<'a, B: ?Sized + Backend>(
353 translation_context: &DeclarationTranslationContext<'a, '_, B>,
354 declarations: &'a Declarations,
355 full_translated_decls: &'a VecMap<BackendDeclaration<B>>,
356 type_: &'a SimpleType,
357 current_namespace_path: &AbsolutePath,
358) -> ResolvedType<'a, B> {
359 match type_ {
360 SimpleType::Struct(index) | SimpleType::Enum(index) => translate_type_index(
361 translation_context,
362 declarations,
363 full_translated_decls,
364 *index,
365 current_namespace_path,
366 ),
367 SimpleType::Bool => ResolvedType::Bool,
368 SimpleType::Integer(typ) => ResolvedType::Integer(*typ),
369 SimpleType::Float(typ) => ResolvedType::Float(*typ),
370 }
371}
372
373fn make_recursive_structure<B: ?Sized + Backend>(
374 declarations: &Declarations,
375 translated_namespaces: &mut VecMap<B::NamespaceInfo>,
376 translated_decls: &mut VecMap<BackendDeclaration<B>>,
377 current_namespace_index: NamespaceIndex,
378) -> BackendNamespace<B> {
379 let (_, current_namespace) = declarations.get_namespace(current_namespace_index);
380 let current_translated_namespace = translated_namespaces
381 .remove(current_namespace_index.0)
382 .unwrap();
383 let translated_declarations: Vec<BackendDeclaration<B>> = current_namespace
384 .declaration_ids
385 .values()
386 .map(|id| translated_decls.remove(id.0).unwrap())
387 .collect();
388
389 let children = current_namespace
390 .child_namespaces
391 .values()
392 .map(|id| {
393 make_recursive_structure(declarations, translated_namespaces, translated_decls, *id)
394 })
395 .collect();
396
397 BackendNamespace {
398 info: current_translated_namespace,
399 children,
400 declarations: translated_declarations,
401 docstrings: current_namespace.docstrings.clone(),
402 }
403}
404
405pub fn run_backend<B: ?Sized + Backend>(
406 backend: &mut B,
407 declarations: &Declarations,
408) -> BackendNamespace<B> {
409 let keywords: Keywords = B::KEYWORDS.iter().copied().collect();
410 let mut global_names = Names::new(&keywords);
411 let global_names = &mut global_names;
412 let mut namespace_names = (0..declarations.namespaces.len())
413 .map(|_| Names::new(&keywords))
414 .collect::<Vec<_>>();
415 let mut declaration_names = (0..declarations.declarations.len())
416 .map(|_| Names::new(&keywords))
417 .collect::<Vec<_>>();
418 let translated_namespaces = declarations
419 .namespaces
420 .iter()
421 .zip(&mut namespace_names)
422 .map(|((namespace_name, namespace), namespace_names)| {
423 backend.generate_namespace(
424 &mut NamespaceNames {
425 _global_names: global_names,
426 namespace_names,
427 },
428 namespace_name,
429 namespace,
430 )
431 })
432 .collect::<Vec<_>>();
433 let translated_decls: Vec<(AbsolutePath, DeclInfo<B>)> = declarations
434 .declarations
435 .iter()
436 .zip(&mut declaration_names)
437 .enumerate()
438 .map(|(decl_id, ((decl_name, decl), declaration_names))| {
439 let namespace_names = &mut namespace_names[decl.namespace_id.0];
440 let decl: DeclInfo<B> = match &decl.kind {
441 DeclarationKind::Table(decl) => DeclInfo::Table(
442 backend.generate_table(
443 &mut DeclarationNames {
444 _global_names: global_names,
445 _namespace_names: namespace_names,
446 declaration_names,
447 },
448 &translated_namespaces,
449 DeclarationIndex(decl_id),
450 decl_name,
451 decl,
452 ),
453 decl,
454 ),
455 DeclarationKind::Struct(decl) => DeclInfo::Struct(
456 backend.generate_struct(
457 &mut DeclarationNames {
458 _global_names: global_names,
459 _namespace_names: namespace_names,
460 declaration_names,
461 },
462 &translated_namespaces,
463 DeclarationIndex(decl_id),
464 decl_name,
465 decl,
466 ),
467 decl,
468 ),
469 DeclarationKind::Enum(decl) => DeclInfo::Enum(
470 backend.generate_enum(
471 &mut DeclarationNames {
472 _global_names: global_names,
473 _namespace_names: namespace_names,
474 declaration_names,
475 },
476 &translated_namespaces,
477 DeclarationIndex(decl_id),
478 decl_name,
479 decl,
480 ),
481 decl,
482 ),
483 DeclarationKind::Union(decl) => DeclInfo::Union(
484 backend.generate_union(
485 &mut DeclarationNames {
486 _global_names: global_names,
487 _namespace_names: namespace_names,
488 declaration_names,
489 },
490 &translated_namespaces,
491 DeclarationIndex(decl_id),
492 decl_name,
493 decl,
494 ),
495 decl,
496 ),
497 DeclarationKind::RpcService(_decl) => todo!(),
498 };
499 (decl_name.clone(), decl)
500 })
501 .collect::<Vec<_>>();
502
503 let mut full_translated_decls: VecMap<BackendDeclaration<B>> =
504 VecMap::with_capacity(declarations.declarations.len());
505
506 for (i, (((_decl_path, decl), orig_decl), declaration_names)) in translated_decls
507 .iter()
508 .zip(&declarations.declarations)
509 .zip(&mut declaration_names)
510 .enumerate()
511 {
512 if let DeclInfo::Enum(translated_decl, decl) = decl {
513 let namespace_names = &mut namespace_names[orig_decl.1.namespace_id.0];
514 full_translated_decls.insert(
515 i,
516 BackendDeclaration::Enum(BackendEnum {
517 size: decl.type_.byte_size(),
518 info: translated_decl.clone(),
519 variants: decl
520 .variants
521 .iter()
522 .map(|(value, variant)| BackendVariant {
523 name_and_docs: NameAndDocstrings {
524 original_name: variant.name.clone(),
525 docstrings: variant.docstrings.clone(),
526 },
527 variant: backend.generate_enum_variant(
528 &mut DeclarationTranslationContext {
529 declaration_names: DeclarationNames {
530 _global_names: global_names,
531 _namespace_names: namespace_names,
532 declaration_names,
533 },
534 translated_namespaces: &translated_namespaces,
535 translated_decls: &translated_decls,
536 },
537 translated_decl,
538 decl,
539 &variant.name,
540 value,
541 ),
542 })
543 .collect(),
544 docstrings: (orig_decl.1).docstrings.clone(),
545 }),
546 );
547 }
548 }
549
550 for (i, (((decl_path, decl), orig_decl), declaration_names)) in translated_decls
551 .iter()
552 .zip(&declarations.declarations)
553 .zip(&mut declaration_names)
554 .enumerate()
555 {
556 let namespace_names = &mut namespace_names[orig_decl.1.namespace_id.0];
557 let mut translation_context = DeclarationTranslationContext {
558 declaration_names: DeclarationNames {
559 _global_names: global_names,
560 _namespace_names: namespace_names,
561 declaration_names,
562 },
563 translated_namespaces: &translated_namespaces,
564 translated_decls: &translated_decls,
565 };
566 let decl = match decl {
567 DeclInfo::Enum(..) => continue,
568 DeclInfo::Table(translated_decl, decl) => BackendDeclaration::Table(BackendTable {
569 max_vtable_size: decl.max_vtable_size,
570 _max_size: decl.max_size,
571 _max_alignment: decl.max_alignment,
572 info: translated_decl.clone(),
573 fields: BackendTableFields::new(
574 declarations,
575 backend,
576 &mut translation_context,
577 &full_translated_decls,
578 decl,
579 decl_path,
580 translated_decl,
581 ),
582 docstrings: (orig_decl.1).docstrings.clone(),
583 }),
584 DeclInfo::Struct(translated_decl, decl) => BackendDeclaration::Struct(BackendStruct {
585 size: decl.size,
586 alignment: decl.alignment,
587 info: translated_decl.clone(),
588 fields: decl
589 .fields
590 .iter()
591 .map(|(field_name, field)| {
592 let translated_type = translate_simple_type(
593 &translation_context,
594 declarations,
595 &full_translated_decls,
596 &field.type_,
597 &decl_path.clone_pop(),
598 );
599 BackendStructField {
600 info: backend.generate_struct_field(
601 &mut translation_context,
602 translated_decl,
603 decl,
604 field_name,
605 field,
606 translated_type,
607 ),
608 offset: field.offset,
609 padding_after_field: field.padding_after_field,
610 size: field.size,
611 name_and_docs: NameAndDocstrings {
612 original_name: field_name.clone(),
613 docstrings: field.docstrings.clone(),
614 },
615 }
616 })
617 .collect(),
618 docstrings: (orig_decl.1).docstrings.clone(),
619 }),
620 DeclInfo::Union(translated_decl, decl) => BackendDeclaration::Union(BackendUnion {
621 info: translated_decl.clone(),
622 variants: decl
623 .variants
624 .iter()
625 .enumerate()
626 .map(|(index, (name, variant))| {
627 let translated_type = translate_type(
628 &translation_context,
629 declarations,
630 &full_translated_decls,
631 &variant.type_,
632 &decl_path.clone_pop(),
633 );
634 BackendVariant {
635 name_and_docs: NameAndDocstrings {
636 original_name: name.clone(),
637 docstrings: variant.docstrings.clone(),
638 },
639 variant: backend.generate_union_variant(
640 &mut translation_context,
641 translated_decl,
642 decl,
643 name,
644 index as u8,
645 variant,
646 translated_type,
647 ),
648 }
649 })
650 .collect(),
651 docstrings: (orig_decl.1).docstrings.clone(),
652 }),
653 DeclInfo::RpcService(_translated_decl, _decl) => todo!(),
654 };
655 full_translated_decls.insert(i, decl);
656 }
657
658 let mut translated_namespaces: VecMap<_> =
659 translated_namespaces.into_iter().enumerate().collect();
660
661 make_recursive_structure(
662 declarations,
663 &mut translated_namespaces,
664 &mut full_translated_decls,
665 declarations.get_root_namespace().0,
666 )
667}