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 forced_alignment: Option<(u32, Span)>,
267    pub deprecated: bool,
268    pub docstrings: Docstrings,
269}
270
271#[derive(Copy, Clone, Debug)]
272/// Indicates whether a [`TableField`] has a preceding tag. Used by unions and union vectors.
273pub enum TableFieldTagKind {
274    None,
275    UnionTag,
276    UnionTagVector,
277}
278
279impl TableFieldTagKind {
280    /// The size of the preceding tag or 0 if not present.
281    pub fn size(self) -> u32 {
282        match self {
283            TableFieldTagKind::None => 0,
284            TableFieldTagKind::UnionTag => 1,
285            TableFieldTagKind::UnionTagVector => 4,
286        }
287    }
288}
289
290#[derive(Clone, Debug)]
291pub enum AssignMode {
292    Required,
293    Optional,
294    HasDefault(Literal),
295}
296
297#[derive(Debug)]
298pub struct Struct {
299    pub fields: IndexMap<String, StructField>,
300    pub size: u32,
301    pub alignment: u32,
302}
303
304#[derive(Debug)]
305pub struct StructField {
306    pub type_: SimpleType,
307    pub offset: u32,
308    pub size: u32,
309    pub padding_after_field: u32,
310    pub docstrings: Docstrings,
311}
312
313#[derive(Debug, Clone)]
314pub struct Enum {
315    pub type_: IntegerType,
316    pub variants: IndexMap<IntegerLiteral, EnumVariant>,
317    pub alignment: u32,
318}
319
320#[derive(Debug, Clone)]
321pub struct EnumVariant {
322    pub span: Span,
323    pub name: String,
324    pub docstrings: Docstrings,
325}
326
327#[derive(Debug)]
328pub struct Union {
329    pub variants: IndexMap<String, UnionVariant>,
330}
331
332#[derive(Debug)]
333pub struct UnionVariant {
334    pub type_: Type,
335    pub docstrings: Docstrings,
336}
337
338#[derive(Debug)]
339pub struct RpcService {
340    pub methods: IndexMap<String, RpcMethod>,
341}
342
343#[derive(Debug)]
344pub struct RpcMethod {
345    pub argument_type: Type,
346    pub return_type: Type,
347}
348
349#[derive(Debug, PartialEq, Eq, Hash)]
350pub struct Type {
351    pub span: Span,
352    pub kind: TypeKind,
353}
354
355impl TypeKind {
356    pub fn is_scalar(&self) -> bool {
357        match self {
358            TypeKind::Table(_)
359            | TypeKind::Union(_)
360            | TypeKind::Vector(_)
361            | TypeKind::Array(_, _)
362            | TypeKind::String => false,
363            TypeKind::SimpleType(type_) => type_.is_scalar(),
364        }
365    }
366
367    pub fn is_enum(&self) -> bool {
368        matches!(self, &TypeKind::SimpleType(SimpleType::Enum(..)))
369    }
370
371    pub fn is_type_with_tag(&self) -> bool {
372        match self {
373            TypeKind::Union(_) => true,
374            TypeKind::Vector(inner) => matches!(inner.kind, TypeKind::Union(_)),
375            _ => false,
376        }
377    }
378
379    fn add_children(&self, children: &mut BTreeSet<DeclarationIndex>) {
380        match self {
381            TypeKind::Table(decl_id) | TypeKind::Union(decl_id) => {
382                children.insert(*decl_id);
383            }
384            TypeKind::Vector(type_) | TypeKind::Array(type_, _) => {
385                type_.kind.add_children(children)
386            }
387            TypeKind::SimpleType(kind) => {
388                kind.add_children(children);
389            }
390            TypeKind::String => (),
391        }
392    }
393}
394
395#[derive(Debug, PartialEq, Eq, Hash)]
396pub enum TypeKind {
397    Table(DeclarationIndex),
398    Union(DeclarationIndex),
399    Vector(Box<Type>),
400    Array(Box<Type>, u32),
401    SimpleType(SimpleType),
402    String,
403}
404
405#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
406pub enum SimpleType {
407    Struct(DeclarationIndex),
408    Enum(DeclarationIndex),
409    Bool,
410    Integer(IntegerType),
411    Float(FloatType),
412}
413
414impl SimpleType {
415    pub fn is_scalar(&self) -> bool {
416        match self {
417            SimpleType::Struct(_) => false,
418            SimpleType::Enum(_)
419            | SimpleType::Bool
420            | SimpleType::Integer(_)
421            | SimpleType::Float(_) => true,
422        }
423    }
424
425    fn add_children(&self, children: &mut BTreeSet<DeclarationIndex>) {
426        match self {
427            SimpleType::Struct(decl_id) | SimpleType::Enum(decl_id) => {
428                children.insert(*decl_id);
429            }
430            SimpleType::Bool | SimpleType::Integer(_) | SimpleType::Float(_) => (),
431        }
432    }
433}
434
435#[derive(Clone, Debug)]
436pub enum Literal {
437    Bool(bool),
438    String(String),
439    Int(IntegerLiteral),
440    Float(FloatLiteral),
441    Array(Vec<Literal>),
442    Vector(Vec<Literal>),
443    EnumTag {
444        variant_index: usize,
445        value: IntegerLiteral,
446    },
447}
448
449#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
450pub enum IntegerLiteral {
451    U8(u8),
452    I8(i8),
453    U16(u16),
454    I16(i16),
455    U32(u32),
456    I32(i32),
457    U64(u64),
458    I64(i64),
459}
460
461impl IntegerLiteral {
462    pub fn is_zero(&self) -> bool {
463        match self {
464            IntegerLiteral::U8(n) => *n == 0,
465            IntegerLiteral::I8(n) => *n == 0,
466            IntegerLiteral::U16(n) => *n == 0,
467            IntegerLiteral::I16(n) => *n == 0,
468            IntegerLiteral::U32(n) => *n == 0,
469            IntegerLiteral::I32(n) => *n == 0,
470            IntegerLiteral::U64(n) => *n == 0,
471            IntegerLiteral::I64(n) => *n == 0,
472        }
473    }
474
475    pub fn to_u64(&self) -> u64 {
476        match self {
477            IntegerLiteral::U8(v) => *v as u64,
478            IntegerLiteral::I8(v) => *v as u64,
479            IntegerLiteral::U16(v) => *v as u64,
480            IntegerLiteral::I16(v) => *v as u64,
481            IntegerLiteral::U32(v) => *v as u64,
482            IntegerLiteral::I32(v) => *v as u64,
483            IntegerLiteral::U64(v) => *v,
484            IntegerLiteral::I64(v) => *v as u64,
485        }
486    }
487}
488
489impl Display for Literal {
490    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
491        match self {
492            Literal::Bool(v) => write!(f, "{v}"),
493            Literal::String(v) => write!(f, "{v}"),
494            Literal::Int(v) => write!(f, "{v}"),
495            Literal::Float(v) => write!(f, "{v}"),
496            Literal::Array(vs) | Literal::Vector(vs) => {
497                write!(f, "[")?;
498                let mut first = true;
499                for v in vs {
500                    if !first {
501                        write!(f, ", {v}")?;
502                    } else {
503                        first = false;
504                        write!(f, "{v}")?;
505                    }
506                }
507                write!(f, "]")
508            }
509            Literal::EnumTag { value, .. } => write!(f, "{value}"),
510        }
511    }
512}
513
514impl Display for IntegerLiteral {
515    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
516        match self {
517            IntegerLiteral::U8(v) => write!(f, "{v}"),
518            IntegerLiteral::I8(v) => write!(f, "{v}"),
519            IntegerLiteral::U16(v) => write!(f, "{v}"),
520            IntegerLiteral::I16(v) => write!(f, "{v}"),
521            IntegerLiteral::U32(v) => write!(f, "{v}"),
522            IntegerLiteral::I32(v) => write!(f, "{v}"),
523            IntegerLiteral::U64(v) => write!(f, "{v}"),
524            IntegerLiteral::I64(v) => write!(f, "{v}"),
525        }
526    }
527}
528
529#[derive(Copy, Clone, Debug)]
530pub enum FloatLiteral {
531    F32(f32),
532    F64(f64),
533}
534
535impl Display for FloatLiteral {
536    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
537        match self {
538            FloatLiteral::F32(v) => write!(f, "{v:?}"),
539            FloatLiteral::F64(v) => write!(f, "{v:?}"),
540        }
541    }
542}
543impl Table {
544    fn children(&self) -> Vec<DeclarationIndex> {
545        let mut children = BTreeSet::new();
546        for field in self.fields.values() {
547            field.type_.kind.add_children(&mut children);
548        }
549        children.into_iter().collect()
550    }
551
552    pub fn get_field_for_vtable_index(
553        &self,
554        vtable_index: u32,
555    ) -> Option<(&str, &TableField, bool)> {
556        for (field_name, field) in &self.fields {
557            if vtable_index == field.vtable_index {
558                return Some((field_name, field, field.type_.kind.is_type_with_tag()));
559            }
560            if vtable_index == field.vtable_index + 1 && field.type_.kind.is_type_with_tag() {
561                return Some((field_name, field, false));
562            }
563        }
564        None
565    }
566}
567
568impl Struct {
569    fn children(&self) -> Vec<DeclarationIndex> {
570        let mut children = BTreeSet::new();
571        for field in self.fields.values() {
572            field.type_.add_children(&mut children);
573        }
574        children.into_iter().collect()
575    }
576}
577
578impl Union {
579    fn children(&self) -> Vec<DeclarationIndex> {
580        let mut children = BTreeSet::new();
581        for variant in self.variants.values() {
582            variant.type_.kind.add_children(&mut children);
583        }
584        children.into_iter().collect()
585    }
586}
587
588impl RpcService {
589    fn children(&self) -> Vec<DeclarationIndex> {
590        let mut children = BTreeSet::new();
591        for method in self.methods.values() {
592            method.argument_type.kind.add_children(&mut children);
593            method.return_type.kind.add_children(&mut children);
594        }
595        children.into_iter().collect()
596    }
597}
598
599impl IntegerLiteral {
600    pub fn default_value_from_type(type_: &crate::ast::IntegerType) -> Self {
601        match type_ {
602            crate::ast::IntegerType::U8 => Self::U8(0),
603            crate::ast::IntegerType::U16 => Self::U16(0),
604            crate::ast::IntegerType::U32 => Self::U32(0),
605            crate::ast::IntegerType::U64 => Self::U64(0),
606            crate::ast::IntegerType::I8 => Self::I8(0),
607            crate::ast::IntegerType::I16 => Self::I16(0),
608            crate::ast::IntegerType::I32 => Self::I32(0),
609            crate::ast::IntegerType::I64 => Self::I64(0),
610        }
611    }
612
613    #[must_use]
614    pub fn next(&self) -> Self {
615        match self {
616            Self::U8(n) => Self::U8(n.wrapping_add(1)),
617            Self::I8(n) => Self::I8(n.wrapping_add(1)),
618            Self::U16(n) => Self::U16(n.wrapping_add(1)),
619            Self::I16(n) => Self::I16(n.wrapping_add(1)),
620            Self::U32(n) => Self::U32(n.wrapping_add(1)),
621            Self::I32(n) => Self::I32(n.wrapping_add(1)),
622            Self::U64(n) => Self::U64(n.wrapping_add(1)),
623            Self::I64(n) => Self::I64(n.wrapping_add(1)),
624        }
625    }
626}
627
628impl From<&crate::ast::BuiltinType> for TypeKind {
629    fn from(value: &crate::ast::BuiltinType) -> TypeKind {
630        match value {
631            crate::ast::BuiltinType::Bool => TypeKind::SimpleType(SimpleType::Bool),
632            crate::ast::BuiltinType::Integer(typ) => {
633                TypeKind::SimpleType(SimpleType::Integer(*typ))
634            }
635            crate::ast::BuiltinType::Float(typ) => TypeKind::SimpleType(SimpleType::Float(*typ)),
636            crate::ast::BuiltinType::String => TypeKind::String,
637        }
638    }
639}