planus_types/
intermediate.rs

1use std::{borrow::Cow, collections::BTreeSet, fmt::Display};
2
3use codespan::{FileId, Span};
4use indexmap::IndexMap;
5
6use crate::ast::{Docstrings, FloatType, IntegerType};
7
8#[derive(Clone, Hash, PartialEq, Eq, Debug)]
9pub struct AbsolutePath(pub Vec<String>);
10
11impl AbsolutePath {
12    pub const ROOT_PATH: Self = Self(Vec::new());
13
14    pub fn push<S: Into<String>>(&mut self, value: S) {
15        self.0.push(value.into())
16    }
17
18    pub fn pop(&mut self) -> Option<String> {
19        self.0.pop()
20    }
21
22    #[must_use]
23    pub fn clone_push<S: AsRef<str>>(&self, value: S) -> Self {
24        let mut r = self.clone();
25        r.push(value.as_ref());
26        r
27    }
28
29    #[must_use]
30    pub fn clone_pop(&self) -> Self {
31        assert!(!self.0.is_empty());
32        Self(self.0[..self.0.len() - 1].to_vec())
33    }
34}
35
36impl std::fmt::Display for AbsolutePath {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        let mut first = true;
39        for part in &self.0 {
40            if first {
41                first = false;
42                write!(f, "{part}")?;
43            } else {
44                write!(f, ".{part}")?;
45            }
46        }
47        Ok(())
48    }
49}
50
51pub struct RelativePath {
52    pub count_until_shared_parent: usize,
53    pub remaining: Vec<String>,
54}
55
56#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub struct DeclarationIndex(pub usize);
58impl DeclarationIndex {
59    pub const INVALID: DeclarationIndex = DeclarationIndex(usize::MAX);
60}
61
62impl Display for DeclarationIndex {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        write!(f, "{}", self.0)
65    }
66}
67
68impl<'a> From<&'a DeclarationIndex> for DeclarationIndex {
69    fn from(decl: &'a DeclarationIndex) -> Self {
70        *decl
71    }
72}
73
74impl<'a, 'b> From<&'b &'a DeclarationIndex> for DeclarationIndex {
75    fn from(decl: &'b &'a DeclarationIndex) -> Self {
76        **decl
77    }
78}
79
80#[derive(Copy, Clone, Debug)]
81pub struct NamespaceIndex(pub usize);
82impl NamespaceIndex {
83    pub const INVALID: NamespaceIndex = NamespaceIndex(usize::MAX);
84}
85
86impl<'a> From<&'a NamespaceIndex> for NamespaceIndex {
87    fn from(namespace: &'a NamespaceIndex) -> Self {
88        *namespace
89    }
90}
91
92impl<'a, 'b> From<&'b &'a NamespaceIndex> for NamespaceIndex {
93    fn from(namespace: &'b &'a NamespaceIndex) -> Self {
94        **namespace
95    }
96}
97
98#[derive(Debug)]
99pub struct Declarations {
100    pub namespaces: IndexMap<AbsolutePath, Namespace>,
101    pub declarations: IndexMap<AbsolutePath, Declaration>,
102    pub children: Vec<Vec<DeclarationIndex>>,
103    pub parents: Vec<Vec<DeclarationIndex>>,
104}
105
106impl Declarations {
107    pub fn new(
108        namespaces: IndexMap<AbsolutePath, Namespace>,
109        declarations: IndexMap<AbsolutePath, Declaration>,
110    ) -> Self {
111        let children = declarations
112            .values()
113            .map(|decl| match &decl.kind {
114                DeclarationKind::Table(decl) => decl.children(),
115                DeclarationKind::Struct(decl) => decl.children(),
116                DeclarationKind::Enum(_) => Vec::new(),
117                DeclarationKind::Union(decl) => decl.children(),
118                DeclarationKind::RpcService(decl) => decl.children(),
119            })
120            .collect::<Vec<_>>();
121
122        let mut parents = (0..declarations.len())
123            .map(|_| Vec::new())
124            .collect::<Vec<_>>();
125        for (parent_decl_id, children) in children.iter().enumerate() {
126            for child_decl_id in children {
127                parents[child_decl_id.0].push(DeclarationIndex(parent_decl_id));
128            }
129        }
130
131        Self {
132            namespaces,
133            declarations,
134            children,
135            parents,
136        }
137    }
138
139    pub fn get_namespace(&self, index: NamespaceIndex) -> (&AbsolutePath, &Namespace) {
140        self.namespaces.get_index(index.0).unwrap()
141    }
142
143    pub fn get_root_namespace(&self) -> (NamespaceIndex, &Namespace) {
144        let (index, _, namespace) = self.namespaces.get_full(&AbsolutePath::ROOT_PATH).unwrap();
145        (NamespaceIndex(index), namespace)
146    }
147
148    pub fn get_declaration(&self, index: DeclarationIndex) -> (&AbsolutePath, &Declaration) {
149        self.declarations.get_index(index.0).unwrap()
150    }
151
152    pub fn iter_declarations(
153        &self,
154    ) -> impl Iterator<Item = (DeclarationIndex, &AbsolutePath, &Declaration)> {
155        self.declarations
156            .iter()
157            .enumerate()
158            .map(|(i, (k, v))| (DeclarationIndex(i), k, v))
159    }
160
161    pub fn format_type_kind(&self, type_: &TypeKind) -> Cow<'static, str> {
162        match type_ {
163            TypeKind::Table(index) => {
164                Cow::Owned(format!("table {}", self.get_declaration(*index).0))
165            }
166            TypeKind::Union(index) => {
167                Cow::Owned(format!("union {}", self.get_declaration(*index).0))
168            }
169            TypeKind::Vector(type_) => {
170                Cow::Owned(format!("[{}]", self.format_type_kind(&type_.kind)))
171            }
172            TypeKind::Array(type_, size) => {
173                Cow::Owned(format!("[{}; {size}]", self.format_type_kind(&type_.kind)))
174            }
175            TypeKind::SimpleType(type_) => self.format_simple_type(type_),
176            TypeKind::String => Cow::Borrowed("string"),
177        }
178    }
179
180    pub fn format_simple_type(&self, type_: &SimpleType) -> Cow<'static, str> {
181        match type_ {
182            SimpleType::Struct(index) => {
183                Cow::Owned(format!("struct {}", self.get_declaration(*index).0))
184            }
185            SimpleType::Enum(index) => {
186                Cow::Owned(format!("enum {}", self.get_declaration(*index).0))
187            }
188            SimpleType::Bool => Cow::Borrowed("bool"),
189            SimpleType::Integer(type_) => Cow::Borrowed(type_.flatbuffer_name()),
190            SimpleType::Float(type_) => Cow::Borrowed(type_.flatbuffer_name()),
191        }
192    }
193}
194
195#[derive(Debug)]
196pub struct Namespace {
197    /// The span is where the namespace path is defined
198    pub spans: Vec<(FileId, Option<Span>)>,
199    pub docstrings: Docstrings,
200    pub child_namespaces: IndexMap<String, NamespaceIndex>,
201    pub declaration_ids: IndexMap<String, DeclarationIndex>,
202}
203
204impl Default for Namespace {
205    fn default() -> Self {
206        Self {
207            spans: Default::default(),
208            docstrings: Docstrings::new(None),
209            child_namespaces: Default::default(),
210            declaration_ids: Default::default(),
211        }
212    }
213}
214
215#[derive(Debug)]
216pub struct Declaration {
217    pub definition_span: Span,
218    pub file_id: FileId,
219    pub namespace_id: NamespaceIndex,
220    pub kind: DeclarationKind,
221    pub docstrings: Docstrings,
222}
223
224#[derive(Debug)]
225pub enum DeclarationKind {
226    Table(Table),
227    Struct(Struct),
228    Enum(Enum),
229    Union(Union),
230    RpcService(RpcService),
231}
232
233impl DeclarationKind {
234    pub fn kind_as_str(&self) -> &'static str {
235        match self {
236            DeclarationKind::Table(_) => "table",
237            DeclarationKind::Struct(_) => "struct",
238            DeclarationKind::Enum(_) => "enum",
239            DeclarationKind::Union(_) => "union",
240            DeclarationKind::RpcService(_) => "rpc_service",
241        }
242    }
243}
244
245#[derive(Debug)]
246pub struct Table {
247    pub fields: IndexMap<String, TableField>,
248    pub alignment_order: Vec<usize>,
249    pub max_size: u32,
250    pub max_vtable_size: u32,
251    pub max_alignment: u32,
252}
253
254#[derive(Debug)]
255pub struct TableField {
256    /// The index into the vtable.
257    /// Not necessarily the same as the index into the IndexMap.
258    pub vtable_index: u32,
259    pub span: Span,
260    pub type_: Type,
261    pub assign_mode: AssignMode,
262    pub object_value_size: u32,
263    pub object_tag_kind: TableFieldTagKind,
264    pub object_alignment_mask: u32,
265    pub object_alignment: u32,
266    pub deprecated: bool,
267    pub docstrings: Docstrings,
268}
269
270#[derive(Copy, Clone, Debug)]
271/// Indicates whether a [`TableField`] has a preceding tag. Used by unions and union vectors.
272pub enum TableFieldTagKind {
273    None,
274    UnionTag,
275    UnionTagVector,
276}
277
278impl TableFieldTagKind {
279    /// The size of the preceding tag or 0 if not present.
280    pub fn size(self) -> u32 {
281        match self {
282            TableFieldTagKind::None => 0,
283            TableFieldTagKind::UnionTag => 1,
284            TableFieldTagKind::UnionTagVector => 4,
285        }
286    }
287}
288
289#[derive(Clone, Debug)]
290pub enum AssignMode {
291    Required,
292    Optional,
293    HasDefault(Literal),
294}
295
296#[derive(Debug)]
297pub struct Struct {
298    pub fields: IndexMap<String, StructField>,
299    pub size: u32,
300    pub alignment: u32,
301}
302
303#[derive(Debug)]
304pub struct StructField {
305    pub type_: SimpleType,
306    pub offset: u32,
307    pub size: u32,
308    pub padding_after_field: u32,
309    pub docstrings: Docstrings,
310}
311
312#[derive(Debug, Clone)]
313pub struct Enum {
314    pub type_: IntegerType,
315    pub variants: IndexMap<IntegerLiteral, EnumVariant>,
316    pub alignment: u32,
317}
318
319#[derive(Debug, Clone)]
320pub struct EnumVariant {
321    pub span: Span,
322    pub name: String,
323    pub docstrings: Docstrings,
324}
325
326#[derive(Debug)]
327pub struct Union {
328    pub variants: IndexMap<String, UnionVariant>,
329}
330
331#[derive(Debug)]
332pub struct UnionVariant {
333    pub type_: Type,
334    pub docstrings: Docstrings,
335}
336
337#[derive(Debug)]
338pub struct RpcService {
339    pub methods: IndexMap<String, RpcMethod>,
340}
341
342#[derive(Debug)]
343pub struct RpcMethod {
344    pub argument_type: Type,
345    pub return_type: Type,
346}
347
348#[derive(Debug, PartialEq, Eq, Hash)]
349pub struct Type {
350    pub span: Span,
351    pub kind: TypeKind,
352}
353
354impl TypeKind {
355    pub fn is_scalar(&self) -> bool {
356        match self {
357            TypeKind::Table(_)
358            | TypeKind::Union(_)
359            | TypeKind::Vector(_)
360            | TypeKind::Array(_, _)
361            | TypeKind::String => false,
362            TypeKind::SimpleType(type_) => type_.is_scalar(),
363        }
364    }
365
366    pub fn is_enum(&self) -> bool {
367        matches!(self, &TypeKind::SimpleType(SimpleType::Enum(..)))
368    }
369
370    pub fn is_type_with_tag(&self) -> bool {
371        match self {
372            TypeKind::Union(_) => true,
373            TypeKind::Vector(inner) => matches!(inner.kind, TypeKind::Union(_)),
374            _ => false,
375        }
376    }
377
378    fn add_children(&self, children: &mut BTreeSet<DeclarationIndex>) {
379        match self {
380            TypeKind::Table(decl_id) | TypeKind::Union(decl_id) => {
381                children.insert(*decl_id);
382            }
383            TypeKind::Vector(type_) | TypeKind::Array(type_, _) => {
384                type_.kind.add_children(children)
385            }
386            TypeKind::SimpleType(kind) => {
387                kind.add_children(children);
388            }
389            TypeKind::String => (),
390        }
391    }
392}
393
394#[derive(Debug, PartialEq, Eq, Hash)]
395pub enum TypeKind {
396    Table(DeclarationIndex),
397    Union(DeclarationIndex),
398    Vector(Box<Type>),
399    Array(Box<Type>, u32),
400    SimpleType(SimpleType),
401    String,
402}
403
404#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
405pub enum SimpleType {
406    Struct(DeclarationIndex),
407    Enum(DeclarationIndex),
408    Bool,
409    Integer(IntegerType),
410    Float(FloatType),
411}
412
413impl SimpleType {
414    pub fn is_scalar(&self) -> bool {
415        match self {
416            SimpleType::Struct(_) => false,
417            SimpleType::Enum(_)
418            | SimpleType::Bool
419            | SimpleType::Integer(_)
420            | SimpleType::Float(_) => true,
421        }
422    }
423
424    fn add_children(&self, children: &mut BTreeSet<DeclarationIndex>) {
425        match self {
426            SimpleType::Struct(decl_id) | SimpleType::Enum(decl_id) => {
427                children.insert(*decl_id);
428            }
429            SimpleType::Bool | SimpleType::Integer(_) | SimpleType::Float(_) => (),
430        }
431    }
432}
433
434#[derive(Clone, Debug)]
435pub enum Literal {
436    Bool(bool),
437    String(String),
438    Int(IntegerLiteral),
439    Float(FloatLiteral),
440    Array(Vec<Literal>),
441    Vector(Vec<Literal>),
442    EnumTag {
443        variant_index: usize,
444        value: IntegerLiteral,
445    },
446}
447
448#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
449pub enum IntegerLiteral {
450    U8(u8),
451    I8(i8),
452    U16(u16),
453    I16(i16),
454    U32(u32),
455    I32(i32),
456    U64(u64),
457    I64(i64),
458}
459
460impl IntegerLiteral {
461    pub fn is_zero(&self) -> bool {
462        match self {
463            IntegerLiteral::U8(n) => *n == 0,
464            IntegerLiteral::I8(n) => *n == 0,
465            IntegerLiteral::U16(n) => *n == 0,
466            IntegerLiteral::I16(n) => *n == 0,
467            IntegerLiteral::U32(n) => *n == 0,
468            IntegerLiteral::I32(n) => *n == 0,
469            IntegerLiteral::U64(n) => *n == 0,
470            IntegerLiteral::I64(n) => *n == 0,
471        }
472    }
473
474    pub fn to_u64(&self) -> u64 {
475        match self {
476            IntegerLiteral::U8(v) => *v as u64,
477            IntegerLiteral::I8(v) => *v as u64,
478            IntegerLiteral::U16(v) => *v as u64,
479            IntegerLiteral::I16(v) => *v as u64,
480            IntegerLiteral::U32(v) => *v as u64,
481            IntegerLiteral::I32(v) => *v as u64,
482            IntegerLiteral::U64(v) => *v,
483            IntegerLiteral::I64(v) => *v as u64,
484        }
485    }
486}
487
488impl Display for Literal {
489    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
490        match self {
491            Literal::Bool(v) => write!(f, "{v}"),
492            Literal::String(v) => write!(f, "{v}"),
493            Literal::Int(v) => write!(f, "{v}"),
494            Literal::Float(v) => write!(f, "{v}"),
495            Literal::Array(vs) | Literal::Vector(vs) => {
496                write!(f, "[")?;
497                let mut first = true;
498                for v in vs {
499                    if !first {
500                        write!(f, ", {v}")?;
501                    } else {
502                        first = false;
503                        write!(f, "{v}")?;
504                    }
505                }
506                write!(f, "]")
507            }
508            Literal::EnumTag { value, .. } => write!(f, "{value}"),
509        }
510    }
511}
512
513impl Display for IntegerLiteral {
514    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
515        match self {
516            IntegerLiteral::U8(v) => write!(f, "{v}"),
517            IntegerLiteral::I8(v) => write!(f, "{v}"),
518            IntegerLiteral::U16(v) => write!(f, "{v}"),
519            IntegerLiteral::I16(v) => write!(f, "{v}"),
520            IntegerLiteral::U32(v) => write!(f, "{v}"),
521            IntegerLiteral::I32(v) => write!(f, "{v}"),
522            IntegerLiteral::U64(v) => write!(f, "{v}"),
523            IntegerLiteral::I64(v) => write!(f, "{v}"),
524        }
525    }
526}
527
528#[derive(Copy, Clone, Debug)]
529pub enum FloatLiteral {
530    F32(f32),
531    F64(f64),
532}
533
534impl Display for FloatLiteral {
535    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
536        match self {
537            FloatLiteral::F32(v) => write!(f, "{v:?}"),
538            FloatLiteral::F64(v) => write!(f, "{v:?}"),
539        }
540    }
541}
542impl Table {
543    fn children(&self) -> Vec<DeclarationIndex> {
544        let mut children = BTreeSet::new();
545        for field in self.fields.values() {
546            field.type_.kind.add_children(&mut children);
547        }
548        children.into_iter().collect()
549    }
550
551    pub fn get_field_for_vtable_index(
552        &self,
553        vtable_index: u32,
554    ) -> Option<(&str, &TableField, bool)> {
555        for (field_name, field) in &self.fields {
556            if vtable_index == field.vtable_index {
557                return Some((field_name, field, field.type_.kind.is_type_with_tag()));
558            }
559            if vtable_index == field.vtable_index + 1 && field.type_.kind.is_type_with_tag() {
560                return Some((field_name, field, false));
561            }
562        }
563        None
564    }
565}
566
567impl Struct {
568    fn children(&self) -> Vec<DeclarationIndex> {
569        let mut children = BTreeSet::new();
570        for field in self.fields.values() {
571            field.type_.add_children(&mut children);
572        }
573        children.into_iter().collect()
574    }
575}
576
577impl Union {
578    fn children(&self) -> Vec<DeclarationIndex> {
579        let mut children = BTreeSet::new();
580        for variant in self.variants.values() {
581            variant.type_.kind.add_children(&mut children);
582        }
583        children.into_iter().collect()
584    }
585}
586
587impl RpcService {
588    fn children(&self) -> Vec<DeclarationIndex> {
589        let mut children = BTreeSet::new();
590        for method in self.methods.values() {
591            method.argument_type.kind.add_children(&mut children);
592            method.return_type.kind.add_children(&mut children);
593        }
594        children.into_iter().collect()
595    }
596}
597
598impl IntegerLiteral {
599    pub fn default_value_from_type(type_: &crate::ast::IntegerType) -> Self {
600        match type_ {
601            crate::ast::IntegerType::U8 => Self::U8(0),
602            crate::ast::IntegerType::U16 => Self::U16(0),
603            crate::ast::IntegerType::U32 => Self::U32(0),
604            crate::ast::IntegerType::U64 => Self::U64(0),
605            crate::ast::IntegerType::I8 => Self::I8(0),
606            crate::ast::IntegerType::I16 => Self::I16(0),
607            crate::ast::IntegerType::I32 => Self::I32(0),
608            crate::ast::IntegerType::I64 => Self::I64(0),
609        }
610    }
611
612    #[must_use]
613    pub fn next(&self) -> Self {
614        match self {
615            Self::U8(n) => Self::U8(n.wrapping_add(1)),
616            Self::I8(n) => Self::I8(n.wrapping_add(1)),
617            Self::U16(n) => Self::U16(n.wrapping_add(1)),
618            Self::I16(n) => Self::I16(n.wrapping_add(1)),
619            Self::U32(n) => Self::U32(n.wrapping_add(1)),
620            Self::I32(n) => Self::I32(n.wrapping_add(1)),
621            Self::U64(n) => Self::U64(n.wrapping_add(1)),
622            Self::I64(n) => Self::I64(n.wrapping_add(1)),
623        }
624    }
625}
626
627impl From<&crate::ast::BuiltinType> for TypeKind {
628    fn from(value: &crate::ast::BuiltinType) -> TypeKind {
629        match value {
630            crate::ast::BuiltinType::Bool => TypeKind::SimpleType(SimpleType::Bool),
631            crate::ast::BuiltinType::Integer(typ) => {
632                TypeKind::SimpleType(SimpleType::Integer(*typ))
633            }
634            crate::ast::BuiltinType::Float(typ) => TypeKind::SimpleType(SimpleType::Float(*typ)),
635            crate::ast::BuiltinType::String => TypeKind::String,
636        }
637    }
638}