Skip to main content

parol/generators/
symbol_table.rs

1//! The module symbol_table provides means to mimic the uniqueness of names per scope.
2//! For auto-generation of symbols we need to adhere these rules of uniqueness.
3use crate::analysis::lookahead_dfa::ProductionIndex;
4use crate::generators::symbol_table_facade::InstanceItem;
5use crate::grammar::{ProductionAttribute, SymbolAttribute};
6use crate::parser::parol_grammar::UserDefinedTypeName;
7use crate::{generators::NamingHelper as NmHlp, utils::generate_name};
8use anyhow::{Result, bail};
9use parol_runtime::log::trace;
10use petgraph::algo::tarjan_scc;
11use petgraph::visit::NodeRef;
12use petgraph::{
13    algo::is_cyclic_directed,
14    dot::{Config, Dot},
15    graph::NodeIndex,
16    prelude::DiGraph,
17};
18use serde::{Deserialize, Serialize};
19use ts_rs::TS;
20
21use std::collections::HashMap;
22use std::fmt::{Debug, Display, Error, Formatter};
23use std::ops::{Index, IndexMut};
24
25use super::symbol_table_facade::{InstanceFacade, SymbolFacade, SymbolItem, TypeFacade, TypeItem};
26
27/// Index type for Symbols
28#[derive(
29    Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, Eq, Hash, Ord, PartialOrd, TS,
30)]
31#[ts(export)]
32pub(crate) struct SymbolId(usize);
33
34impl Display for SymbolId {
35    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
36        write!(f, "Sym({})", self.0)
37    }
38}
39
40/// Scope local index type for SymbolNames
41#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
42#[ts(export)]
43pub(crate) struct ScopedNameId(ScopeId, usize);
44
45impl ScopedNameId {
46    pub(crate) fn is_unnamed(&self) -> bool {
47        self.1 == Scope::UNNAMED_TYPE_NAME_ID
48    }
49}
50
51impl Display for ScopedNameId {
52    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
53        write!(f, "Nam({}, {})", self.0, self.1)
54    }
55}
56
57/// Id type for Scopes
58#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
59#[ts(export)]
60pub(crate) struct ScopeId(usize);
61
62impl Display for ScopeId {
63    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
64        write!(f, "Sco({})", self.0)
65    }
66}
67
68///
69/// Type specificities of a function type
70///
71#[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
72#[ts(export)]
73pub(crate) struct Function {
74    /// Associated non-terminal
75    pub(crate) non_terminal: String,
76
77    /// Semantic specification
78    #[builder(default)]
79    pub(crate) sem: ProductionAttribute,
80
81    /// Production number
82    #[builder(default)]
83    pub(crate) prod_num: ProductionIndex,
84
85    /// The relative index of a production within its alternatives.
86    #[builder(default)]
87    pub(crate) rel_idx: usize,
88
89    /// Number of alternatives, the number of productions that exist in the grammar which have the
90    /// same non-terminal
91    #[builder(default)]
92    pub(crate) alts: usize,
93
94    /// Formatted production in PAR syntax.
95    #[builder(default)]
96    pub(crate) prod_string: String,
97}
98
99impl Function {
100    pub(crate) fn to_rust(&self, fn_name: String) -> String {
101        format!(
102            "fn {} /* NT: {}{} Prod: {}, Rel: {}, Alts: {} */",
103            fn_name,
104            self.non_terminal,
105            match self.sem {
106                ProductionAttribute::None => "".to_string(),
107                _ => format!(", {}", self.sem),
108            },
109            self.prod_num,
110            self.rel_idx,
111            self.alts,
112        )
113    }
114}
115
116#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, TS)]
117#[ts(export)]
118pub(crate) enum MetaSymbolKind {
119    /// A part of a scoped name, normally a module name
120    Module,
121    /// A token
122    Token,
123    /// A non-terminal with inner non-terminal type
124    NonTerminal(SymbolId),
125}
126
127impl Display for MetaSymbolKind {
128    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
129        match self {
130            MetaSymbolKind::Module => write!(f, "Module"),
131            MetaSymbolKind::Token => write!(f, "Tok"),
132            MetaSymbolKind::NonTerminal(t) => write!(f, "Nt({t})"),
133        }
134    }
135}
136
137///
138/// Type information used for auto-generation
139///
140#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TS)]
141#[ts(export)]
142#[derive(Default)]
143pub(crate) enum TypeEntrails {
144    /// Not specified, used as prototype during generation
145    #[default]
146    None,
147    /// Will be generated as Token structure
148    Token,
149    /// A type with Box semantic
150    Box(SymbolId),
151    /// A type with Ref semantic an mutable state
152    Ref(SymbolId),
153    /// A type that refers to another type. Typically used when the type was a boxed type before
154    Surrogate(SymbolId),
155    /// A struct, i.e. a named collection of (name, type) tuples
156    Struct,
157    /// Will be generated as enum with given name
158    Enum,
159    /// A variant of an enum with a type specified by SymbolId
160    EnumVariant(SymbolId),
161    /// Will be generated as `Vec<T>` where T is the type specified by SymbolId
162    Vec(SymbolId),
163    /// A trait, normally the semantic actions trait generated for the user grammar
164    Trait,
165    /// A trait function
166    Function(Function),
167    /// An Option type of a type specified by SymbolId
168    Option(SymbolId),
169    /// An invisible type
170    Clipped(MetaSymbolKind),
171    /// User defined type
172    UserDefinedType(MetaSymbolKind, UserDefinedTypeName),
173}
174
175impl TypeEntrails {
176    pub(crate) fn inner_name(&self, symbol_table: &SymbolTable) -> String {
177        match self {
178            TypeEntrails::Box(t)
179            | TypeEntrails::Surrogate(t)
180            | TypeEntrails::Ref(t)
181            | TypeEntrails::Vec(t)
182            | TypeEntrails::Option(t)
183            | TypeEntrails::UserDefinedType(MetaSymbolKind::NonTerminal(t), _) => {
184                symbol_table.symbol(*t).name()
185            }
186            _ => "No inner name available!".to_string(),
187        }
188    }
189
190    pub(crate) fn sem(&self) -> SymbolAttribute {
191        SymbolAttribute::None
192    }
193
194    pub(crate) fn is_container(&self) -> bool {
195        matches!(self, Self::Vec(_) | Self::Option(_) | Self::Box(_))
196    }
197}
198
199///
200/// Type information used for auto-generation
201///
202#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
203#[ts(export)]
204pub(crate) struct Type {
205    /// The type specificities
206    pub(crate) entrails: TypeEntrails,
207
208    /// The inner scope
209    pub(crate) member_scope: ScopeId,
210}
211
212impl Type {
213    pub(crate) fn to_rust(&self, symbol_table: &SymbolTable, my_symbol: &Symbol) -> String {
214        // self.entrails.to_rust(my_symbol.my_id, symbol_table)
215        let uses_type_name = || {
216            matches!(self.entrails, TypeEntrails::Struct)
217                | matches!(self.entrails, TypeEntrails::Enum)
218                | matches!(self.entrails, TypeEntrails::EnumVariant(_))
219                | matches!(self.entrails, TypeEntrails::Function(_))
220                | matches!(self.entrails, TypeEntrails::Trait)
221        };
222        let my_type_name = if uses_type_name() {
223            let my_type = symbol_table.symbol_as_type(my_symbol.my_id);
224            my_type.inner_name()
225        } else {
226            symbol_table.name(my_symbol.my_id).to_owned()
227        };
228        let lifetime = symbol_table.lifetime(my_symbol.my_id);
229        match &self.entrails {
230            TypeEntrails::None => "*TypeError*".to_string(),
231            TypeEntrails::Token => format!("Token{lifetime}"),
232            TypeEntrails::Box(r) => {
233                format!("Box<{}>", symbol_table.symbol(*r).to_rust())
234            }
235            TypeEntrails::Ref(r) => {
236                let inner_type = symbol_table.symbol(*r);
237                format!("&{}", inner_type.to_rust())
238            }
239            TypeEntrails::Struct => format!("{my_type_name}{lifetime}"),
240            TypeEntrails::Enum => format!("{my_type_name}{lifetime}"),
241            TypeEntrails::EnumVariant(t) => {
242                format!(
243                    "{}({}),",
244                    my_type_name,
245                    symbol_table.symbol_as_type(*t).to_rust(),
246                )
247            }
248            TypeEntrails::Vec(r) => format!(
249                "Vec<{}{}>",
250                symbol_table.symbol(*r).name(),
251                symbol_table.lifetime(*r)
252            ),
253            TypeEntrails::Trait => format!("trait {my_type_name}{lifetime}"),
254            TypeEntrails::Function(f) => f.to_rust(my_type_name),
255            TypeEntrails::Option(o) => format!("Option<{}>", symbol_table.symbol(*o).to_rust()),
256            TypeEntrails::Clipped(k) => format!("Clipped({k})"),
257            TypeEntrails::UserDefinedType(_, u) => u.get_module_scoped_name(),
258            TypeEntrails::Surrogate(s) => format!(
259                "{}{}",
260                symbol_table.symbol(*s).name(),
261                symbol_table.lifetime(*s)
262            ),
263        }
264    }
265
266    /// Returns the name of the wrapped type
267    pub(crate) fn inner_name(&self, symbol_table: &SymbolTable, my_symbol: &Symbol) -> String {
268        let is_user_defined_type = matches!(self.entrails, TypeEntrails::UserDefinedType(..));
269        if is_user_defined_type || my_symbol.name_id.is_unnamed() {
270            self.entrails.inner_name(symbol_table)
271        } else {
272            symbol_table.name(my_symbol.my_id).to_string()
273        }
274    }
275
276    /// Returns the type id behind the symbol
277    pub(crate) fn inner_type(&self) -> Option<SymbolId> {
278        match self.entrails {
279            TypeEntrails::Box(t)
280            | TypeEntrails::Surrogate(t)
281            | TypeEntrails::Ref(t)
282            | TypeEntrails::EnumVariant(t)
283            | TypeEntrails::Vec(t)
284            | TypeEntrails::Option(t) => Some(t),
285            _ => None,
286        }
287    }
288
289    pub(crate) fn sem(&self) -> SymbolAttribute {
290        self.entrails.sem()
291    }
292}
293
294///
295/// Instance specificities
296///
297#[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
298#[ts(export)]
299pub(crate) struct InstanceEntrails {
300    /// Indicates if the argument is used
301    #[builder(default)]
302    pub(crate) used: bool,
303}
304
305///
306/// A typed instance, usually a function argument or a struct member
307///
308#[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
309#[ts(export)]
310pub(crate) struct Instance {
311    /// The scope where the instance resides
312    pub(crate) scope: ScopeId,
313
314    /// The instance's type id in the symbol table
315    pub(crate) type_id: SymbolId,
316
317    /// Instance specificities
318    pub(crate) entrails: InstanceEntrails,
319
320    /// Semantic information
321    pub(crate) sem: SymbolAttribute,
322
323    /// Description
324    pub(crate) description: String,
325}
326
327impl Instance {
328    fn to_rust(&self, symbol_table: &SymbolTable, my_symbol: &Symbol) -> String {
329        let desc = if self.description.is_empty() {
330            String::default()
331        } else {
332            // "*/" and "/*" must be escaped
333            format!(
334                "/* {} */",
335                self.description.replace("*/", "*\\/").replace("/*", "/\\*")
336            )
337        };
338        format!(
339            "{}: {}, {}",
340            self.name(symbol_table, my_symbol),
341            symbol_table.symbol(self.type_id).to_rust(),
342            desc,
343        )
344    }
345
346    pub(crate) fn name(&self, symbol_table: &SymbolTable, my_symbol: &Symbol) -> String {
347        symbol_table.name(my_symbol.my_id).to_string()
348    }
349
350    fn inner_type(&self) -> Option<SymbolId> {
351        Some(self.type_id)
352    }
353
354    pub(crate) fn sem(&self) -> SymbolAttribute {
355        self.sem
356    }
357}
358
359///
360/// A more general symbol
361///
362#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TS)]
363#[ts(export)]
364pub(crate) enum SymbolKind {
365    Type(Type),
366    Instance(Instance),
367}
368
369///
370/// A more general symbol used in the symbol table
371///
372#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TS)]
373#[ts(export)]
374pub struct Symbol {
375    /// The symbol's id in the symbol table
376    pub(crate) my_id: SymbolId,
377
378    /// The symbol name's id in the enveloping scope
379    pub(crate) name_id: ScopedNameId,
380
381    /// The symbol's interior
382    pub(crate) kind: SymbolKind,
383
384    /// If a lifetime is present
385    pub(crate) has_lifetime: bool,
386}
387
388impl Symbol {
389    pub(crate) fn new(
390        my_id: SymbolId,
391        name_id: ScopedNameId,
392        kind: SymbolKind,
393        lifetime: bool,
394    ) -> Self {
395        Self {
396            my_id,
397            name_id,
398            kind,
399            has_lifetime: lifetime,
400        }
401    }
402
403    pub(crate) fn my_id(&self) -> SymbolId {
404        self.my_id
405    }
406
407    fn inner_type(&self) -> Option<SymbolId> {
408        match &self.kind {
409            SymbolKind::Type(t) => t.inner_type(),
410            SymbolKind::Instance(i) => i.inner_type(),
411        }
412    }
413
414    /// Replace the inner type of the symbol
415    fn set_inner_type(&mut self, inner_type: SymbolId) -> Result<()> {
416        match &mut self.kind {
417            SymbolKind::Type(t) => match t.entrails {
418                TypeEntrails::Box(ref mut i)
419                | TypeEntrails::Ref(ref mut i)
420                | TypeEntrails::Surrogate(ref mut i)
421                | TypeEntrails::EnumVariant(ref mut i)
422                | TypeEntrails::Vec(ref mut i)
423                | TypeEntrails::Option(ref mut i)
424                | TypeEntrails::Clipped(MetaSymbolKind::NonTerminal(ref mut i)) => {
425                    *i = inner_type;
426                }
427                _ => bail!("Have no inner type!"),
428            },
429            SymbolKind::Instance(_) => bail!("Ain't no type!"),
430        }
431        Ok(())
432    }
433
434    pub(crate) fn to_rust(&self, symbol_table: &SymbolTable) -> String {
435        match &self.kind {
436            SymbolKind::Type(t) => t.to_rust(symbol_table, self),
437            SymbolKind::Instance(i) => i.to_rust(symbol_table, self),
438        }
439    }
440
441    pub(crate) fn member_scope(&self) -> Option<ScopeId> {
442        match &self.kind {
443            SymbolKind::Type(t) => Some(t.member_scope),
444            SymbolKind::Instance(_) => None,
445        }
446    }
447
448    pub(crate) fn sem(&self) -> SymbolAttribute {
449        match &self.kind {
450            SymbolKind::Type(t) => t.sem(),
451            SymbolKind::Instance(i) => i.sem(),
452        }
453    }
454}
455///
456/// Scope with symbols inside
457///
458#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TS)]
459#[ts(export)]
460pub(crate) struct Scope {
461    pub(crate) parent: Option<ScopeId>,
462    pub(crate) my_id: ScopeId,
463    pub(crate) symbols: Vec<SymbolId>,
464    names: Vec<String>,
465}
466
467impl Scope {
468    const UNNAMED_TYPE_NAME_ID: usize = 0;
469
470    pub(crate) fn new(parent: Option<ScopeId>, my_id: ScopeId) -> Self {
471        Self {
472            parent,
473            my_id,
474            symbols: Vec::new(),
475            names: vec![SymbolTable::UNNAMED_TYPE.to_string()],
476        }
477    }
478
479    pub(crate) fn make_unique_name(&self, preferred_name: String) -> String {
480        if preferred_name == SymbolTable::UNNAMED_TYPE {
481            SymbolTable::UNNAMED_TYPE.to_string()
482        } else {
483            generate_name(self.names.iter(), preferred_name)
484        }
485    }
486
487    pub(crate) fn add_name(&mut self, name: String) -> ScopedNameId {
488        if name == SymbolTable::UNNAMED_TYPE {
489            ScopedNameId(self.my_id, Self::UNNAMED_TYPE_NAME_ID)
490        } else {
491            let name_id = ScopedNameId(self.my_id, self.names.len());
492            self.names.push(name);
493            name_id
494        }
495    }
496
497    fn insert_type(
498        &mut self,
499        name: &str,
500        symbol_id: SymbolId,
501        member_scope: ScopeId,
502        entrails: TypeEntrails,
503    ) -> Symbol {
504        let type_name = match entrails {
505            TypeEntrails::Function(_) => self.make_unique_name(NmHlp::to_lower_snake_case(name)),
506            TypeEntrails::UserDefinedType(..) => name.to_owned(),
507            _ => self.make_unique_name(NmHlp::to_upper_camel_case(name)),
508        };
509        trace!(
510            "Scope {}: Inserting type {}({}) {:?}",
511            self.my_id, type_name, symbol_id, entrails
512        );
513        let name_id = self.add_name(type_name);
514        self.symbols.push(symbol_id);
515        Symbol::new(
516            symbol_id,
517            name_id,
518            SymbolKind::Type(Type {
519                entrails,
520                member_scope,
521            }),
522            false,
523        )
524    }
525
526    fn insert_instance(
527        &mut self,
528        name: &str,
529        symbol_id: SymbolId,
530        type_id: SymbolId,
531        entrails: InstanceEntrails,
532        sem: SymbolAttribute,
533        description: &str,
534    ) -> Symbol {
535        let instance_name = self.make_unique_name(NmHlp::to_lower_snake_case(name));
536        let name_id = self.add_name(instance_name);
537        self.symbols.push(symbol_id);
538        trace!(
539            "Scope {}: Inserting instance {}({}) (type: {}) {:?}",
540            self.my_id, name, symbol_id, type_id, entrails
541        );
542        Symbol::new(
543            symbol_id,
544            name_id,
545            SymbolKind::Instance(Instance {
546                scope: self.my_id,
547                type_id,
548                entrails,
549                sem,
550                description: description.to_owned(),
551            }),
552            false,
553        )
554    }
555
556    fn has_symbol(&self, symbol_id: SymbolId) -> bool {
557        self.symbols.contains(&symbol_id)
558    }
559
560    pub(crate) fn symbol_by_name(
561        &self,
562        symbol_table: &SymbolTable,
563        name: &str,
564    ) -> Option<SymbolId> {
565        self.symbols
566            .iter()
567            .find(|s| {
568                let symbol = symbol_table.symbol(**s);
569                debug_assert_eq!(symbol.name_id().0, self.my_id);
570                self.names[symbol.name_id().1] == name
571            })
572            .copied()
573    }
574
575    pub(crate) fn to_rust(&self, symbol_table: &SymbolTable) -> String {
576        let mut result = String::new();
577        result.push_str(&format!("// Scope: {}\n", self.my_id));
578        for symbol_id in &self.symbols {
579            result.push_str(&format!("{}\n", symbol_table.symbol(*symbol_id).to_rust()));
580        }
581        result
582    }
583}
584
585impl Display for Scope {
586    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
587        write!(
588            f,
589            "// Scope: my_id: {}, parent: {}\n//   Symbols:\n{}\n//   Names:\n{}",
590            self.my_id,
591            self.parent
592                .map_or("No parent".to_string(), |i| format!("{i}")),
593            self.symbols
594                .iter()
595                .map(|s| s.to_string())
596                .collect::<Vec<String>>()
597                .join("\n"),
598            self.names
599                .iter()
600                .enumerate()
601                .map(|(i, n)| format!("{}: {}", ScopedNameId(self.my_id, i), n))
602                .collect::<Vec<String>>()
603                .join("\n"),
604        )
605    }
606}
607
608///
609/// Collection of symbols
610///
611/// Mimics rust's rules of uniqueness of symbol names within a certain scope.
612/// This struct models the scopes and symbols within them only to the extend needed to auto-generate
613/// flawless type and instance names.
614/// Especially the deduction of the existence of lifetime parameter on generated types is modelled
615/// as simple as possible.
616///
617#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TS)]
618#[ts(export)]
619pub struct SymbolTable {
620    // All symbols, ever created
621    pub(crate) symbols: Vec<Symbol>,
622
623    // All scopes
624    // The one and only global scope has always index 0
625    pub(crate) scopes: Vec<Scope>,
626}
627
628impl SymbolTable {
629    pub(crate) const GLOBAL_SCOPE: ScopeId = ScopeId(0);
630    // Some type symbols don't have a user defined name. You can think of it as built in types.
631    // Regarding their names those types are identical. The differences are determined by other
632    // properties. We need not to keep track of their individual names.
633    pub(crate) const UNNAMED_TYPE: &'static str = "";
634
635    /// Creates a new symbol table
636    pub(crate) fn new() -> Self {
637        Self {
638            symbols: Vec::new(),
639            scopes: vec![Scope::new(None, Self::GLOBAL_SCOPE)],
640        }
641    }
642
643    /// Returns the number of symbols in the symbol table which can be used as id for the next
644    /// symbol to be created
645    pub(crate) fn next_symbol_id(&self) -> SymbolId {
646        SymbolId(self.symbols.len())
647    }
648
649    /// Returns the number of scopes in the symbol table which can be used as id for the next
650    /// scope to be created
651    pub(crate) fn next_scope_id(&self) -> ScopeId {
652        ScopeId(self.scopes.len())
653    }
654
655    /// Returns true if the symbol has a lifetime
656    pub(crate) fn has_lifetime(&self, symbol_id: SymbolId) -> bool {
657        self[symbol_id].has_lifetime
658    }
659
660    /// Returns the string representation of the lifetime of the symbol
661    pub(crate) fn lifetime(&self, symbol_id: SymbolId) -> String {
662        if self[symbol_id].has_lifetime {
663            "<'t>".to_string()
664        } else {
665            "".to_string()
666        }
667    }
668
669    /// Returns the string representation of the elided lifetime of the symbol
670    pub(crate) fn elided_lifetime(&self, symbol_id: SymbolId) -> String {
671        if self[symbol_id].has_lifetime {
672            "<'_>".to_string()
673        } else {
674            "".to_string()
675        }
676    }
677
678    /// Returns the name of the symbol
679    pub(crate) fn name(&self, symbol_id: SymbolId) -> &str {
680        let name_id = &self[symbol_id].name_id;
681        &self.scope(name_id.0).names[name_id.1]
682    }
683
684    /// Returns a reference to the member symbols of the given type
685    pub(crate) fn members(&self, type_id: SymbolId) -> Result<&[SymbolId]> {
686        let type_symbol = self.symbol_as_type(type_id);
687        Ok(&self.scope(type_symbol.member_scope()).symbols)
688    }
689
690    /// Returns a reference to the scope with the given id
691    pub(crate) fn scope(&self, scope_id: ScopeId) -> &Scope {
692        &self[scope_id]
693    }
694
695    /// Returns a mutable reference to the scope with the given id
696    pub(crate) fn scope_mut(&mut self, scope_id: ScopeId) -> &mut Scope {
697        &mut self[scope_id]
698    }
699
700    /// Returns a symbol facade of the symbol with the given id
701    pub(crate) fn symbol(&self, symbol_id: SymbolId) -> impl SymbolFacade<'_> {
702        SymbolItem::new(&self[symbol_id], self)
703    }
704
705    /// Returns the type name behind the symbol
706    pub(crate) fn type_name(&self, symbol_id: SymbolId) -> Result<String> {
707        let type_symbol = self.symbol(symbol_id);
708        debug_assert!(matches!(type_symbol.kind(), SymbolKind::Type(_)));
709        Ok(type_symbol.name())
710    }
711
712    /// Returns the instance name behind the symbol
713    pub(crate) fn _instance_name(&self, symbol_id: SymbolId) -> Result<String> {
714        let instance_symbol = self.symbol(symbol_id);
715        debug_assert!(matches!(instance_symbol.kind(), SymbolKind::Instance(_)));
716        Ok(instance_symbol.name())
717    }
718
719    /// Returns an instance facade of the symbol with the given id
720    pub(crate) fn symbol_as_instance(&self, symbol_id: SymbolId) -> impl InstanceFacade<'_> {
721        let instance_symbol = self.symbol(symbol_id);
722        debug_assert!(
723            matches!(instance_symbol.kind(), SymbolKind::Instance(_)),
724            "Symbol {} is not an instance: {:?}!",
725            symbol_id,
726            instance_symbol.kind()
727        );
728        let instance = match &self[symbol_id].kind {
729            SymbolKind::Type(_) => panic!("Ain't no instance!"),
730            SymbolKind::Instance(i) => i,
731        };
732        InstanceItem::new(SymbolItem::new(&self[symbol_id], self), instance)
733    }
734
735    /// Sets the used flag of the symbol with the given id
736    pub(crate) fn set_instance_used(&mut self, symbol_id: SymbolId, used: bool) -> Result<()> {
737        match &mut self[symbol_id].kind {
738            SymbolKind::Type(_) => bail!("Ain't no instance!"),
739            SymbolKind::Instance(i) => i.entrails.used &= used,
740        }
741        Ok(())
742    }
743
744    /// Returns a type facade of the symbol with the given id
745    pub(crate) fn symbol_as_type(&self, symbol_id: SymbolId) -> impl TypeFacade<'_> {
746        let symbol_type = match &self[symbol_id].kind {
747            SymbolKind::Type(t) => t,
748            SymbolKind::Instance(_) => panic!("Ain't no type!"),
749        };
750        TypeItem::new(SymbolItem::new(&self[symbol_id], self), symbol_type)
751    }
752
753    /// Returns the function entrails of the symbol with the given id
754    pub(crate) fn symbol_as_function(&self, symbol_id: SymbolId) -> Result<Function> {
755        let function_type = self.symbol_as_type(symbol_id);
756        match function_type.entrails() {
757            TypeEntrails::Function(f) => Ok(f.clone()),
758            _ => bail!("Expecting a function here"),
759        }
760    }
761
762    /// Returns the function semantic of the symbol with the given id
763    pub(crate) fn function_type_semantic(
764        &self,
765        symbol_id: SymbolId,
766    ) -> Result<ProductionAttribute> {
767        let function_type = self.symbol_as_type(symbol_id);
768        match function_type.entrails() {
769            TypeEntrails::Function(f) => Ok(f.sem),
770            _ => bail!("Expecting a function here"),
771        }
772    }
773
774    /// Creates a new scope and returns its id
775    fn insert_scope(&mut self, parent: Option<ScopeId>) -> ScopeId {
776        let my_id = self.next_scope_id();
777        self.scopes.push(Scope::new(parent, my_id));
778        my_id
779    }
780
781    /// Creates a new symbol and returns its id
782    fn insert_symbol(&mut self, mut symbol: Symbol) -> SymbolId {
783        let symbol_id = self.next_symbol_id();
784        let is_clipped = symbol.sem() == SymbolAttribute::Clipped;
785        symbol.has_lifetime = !is_clipped
786            && matches!(
787                symbol.kind,
788                SymbolKind::Type(Type {
789                    entrails: TypeEntrails::Token,
790                    ..
791                })
792            );
793        self.symbols.push(symbol);
794        symbol_id
795    }
796
797    /// Returns all scopes that contain the symbol with the given id
798    fn find_containing_scopes(&self, symbol_id: SymbolId) -> Vec<ScopeId> {
799        self.scopes
800            .iter()
801            .filter(|scope| scope.has_symbol(symbol_id))
802            .map(|scope| scope.my_id)
803            .collect::<Vec<ScopeId>>()
804    }
805
806    /// Returns all symbols that have a member scope that is contained in the given scopes
807    fn find_symbols_with_member_scopes(&self, scope_ids: &[ScopeId]) -> Vec<SymbolId> {
808        self.symbols
809            .iter()
810            .filter(|symbol| {
811                if let Some(scope) = symbol.member_scope() {
812                    symbol.sem() != SymbolAttribute::Clipped && scope_ids.contains(&scope)
813                } else {
814                    false
815                }
816            })
817            .map(|symbol| symbol.my_id())
818            .collect::<Vec<SymbolId>>()
819    }
820
821    /// Returns all symbols that have a lifetime
822    fn symbols_with_lifetime(&self) -> Vec<SymbolId> {
823        self.symbols
824            .iter()
825            .enumerate()
826            .filter_map(|(i, symbol)| {
827                if symbol.has_lifetime {
828                    debug_assert_eq!(i, symbol.my_id().0);
829                    Some(symbol.my_id())
830                } else {
831                    None
832                }
833            })
834            .collect::<Vec<SymbolId>>()
835    }
836
837    /// Propagates the lifetime from the given symbol up to the containing scopes
838    fn propagate_lifetime(&mut self, symbol_id: SymbolId) {
839        let parent_scope_ids = self.find_containing_scopes(symbol_id);
840        let parent_symbols = self.find_symbols_with_member_scopes(&parent_scope_ids);
841        for parent_symbol in &parent_symbols {
842            self[*parent_symbol].has_lifetime = true;
843        }
844        let containing_symbols = self
845            .symbols
846            .iter()
847            .filter(|symbol| {
848                if let Some(inner_type) = symbol.inner_type() {
849                    inner_type == symbol_id
850                } else {
851                    false
852                }
853            })
854            .map(|symbol| symbol.my_id())
855            .collect::<Vec<SymbolId>>();
856
857        for containing_symbol in &containing_symbols {
858            self[*containing_symbol].has_lifetime = true;
859        }
860    }
861
862    /// Propagates lifetimes from the bottom up
863    pub(crate) fn propagate_lifetimes(&mut self) {
864        let mut symbols_with_lifetime = self.symbols_with_lifetime();
865        let mut count = symbols_with_lifetime.len();
866        let mut old_count = 0;
867        while count != old_count {
868            old_count = count;
869            for symbol_id in symbols_with_lifetime {
870                self.propagate_lifetime(symbol_id);
871            }
872            symbols_with_lifetime = self.symbols_with_lifetime();
873            count = symbols_with_lifetime.len();
874        }
875    }
876
877    /// Creates a new type symbol with the given name and type in the given scope and returns its id
878    pub(crate) fn insert_type(
879        &mut self,
880        parent_symbol: SymbolId,
881        type_name: &str,
882        entrails: TypeEntrails,
883    ) -> Result<SymbolId> {
884        debug_assert!(parent_symbol.0 < self.symbols.len());
885        let parent_scope = self
886            .scope(self.symbol_as_type(parent_symbol).member_scope())
887            .my_id;
888        self.insert_type_in_scope(parent_scope, type_name, entrails)
889    }
890
891    /// Creates a new type symbol with the given name and type in the given scope and returns its id
892    pub(crate) fn insert_type_in_scope(
893        &mut self,
894        parent_scope: ScopeId,
895        type_name: &str,
896        entrails: TypeEntrails,
897    ) -> Result<SymbolId> {
898        let symbol_id = self.next_symbol_id();
899        let member_scope = self.insert_scope(Some(parent_scope));
900        let symbol =
901            self.scope_mut(parent_scope)
902                .insert_type(type_name, symbol_id, member_scope, entrails);
903        Ok(self.insert_symbol(symbol))
904    }
905
906    /// Creates a new type symbol with the given name and type in the global scope and returns its
907    /// id
908    pub(crate) fn insert_global_type(
909        &mut self,
910        type_name: &str,
911        entrails: TypeEntrails,
912    ) -> Result<SymbolId> {
913        let symbol_id = self.next_symbol_id();
914        let member_scope = self.insert_scope(Some(SymbolTable::GLOBAL_SCOPE));
915        let symbol = self.scope_mut(Self::GLOBAL_SCOPE).insert_type(
916            type_name,
917            symbol_id,
918            member_scope,
919            entrails,
920        );
921        Ok(self.insert_symbol(symbol))
922    }
923
924    /// Creates a new instance symbol with the given name and type in the given scope and returns
925    /// its id
926    pub(crate) fn insert_instance(
927        &mut self,
928        parent_symbol: SymbolId,
929        instance_name: &str,
930        type_id: SymbolId,
931        entrails: InstanceEntrails,
932        sem: SymbolAttribute,
933        description: &str,
934    ) -> Result<SymbolId> {
935        debug_assert!(parent_symbol.0 < self.symbols.len());
936        let symbol_id = self.next_symbol_id();
937        let member_scope = self.symbol_as_type(parent_symbol).member_scope();
938        let symbol = self.scope_mut(member_scope).insert_instance(
939            instance_name,
940            symbol_id,
941            type_id,
942            entrails,
943            sem,
944            description,
945        );
946        Ok(self.insert_symbol(symbol))
947    }
948
949    /// Returns the symbol id of the type with the given name in the given scope
950    /// If the type does not exist, it will be created
951    pub(crate) fn get_or_create_type(
952        &mut self,
953        type_name: &str,
954        scope: ScopeId,
955        entrails: TypeEntrails,
956    ) -> Result<SymbolId> {
957        if let Some(symbol_id) = self.scope(scope).symbols.iter().find(|symbol_id| {
958            let type_symbol = self.symbol_as_type(**symbol_id);
959            *type_symbol.entrails() == entrails && self.name(**symbol_id) == type_name
960        }) {
961            return Ok(*symbol_id);
962        }
963
964        // Here we have to create a new type
965        if scope == Self::GLOBAL_SCOPE {
966            self.insert_global_type(type_name, entrails)
967        } else {
968            self.insert_type_in_scope(scope, type_name, entrails)
969        }
970    }
971
972    /// Returns the symbol id of the type with the given name in the global scope
973    pub(crate) fn get_global_type(&self, non_terminal: &str) -> Option<SymbolId> {
974        self.scope(Self::GLOBAL_SCOPE)
975            .symbols
976            .iter()
977            .find(|symbol_id| self.name(**symbol_id) == non_terminal)
978            .copied()
979    }
980
981    /// Creates a new type whose name is interpreted as scoped name.
982    /// The scopes are created if necessary.
983    /// The type is created if necessary in the inner most scope.
984    pub(crate) fn get_or_create_scoped_user_defined_type(
985        &mut self,
986        symbol_kind: MetaSymbolKind,
987        user_defined_type: &UserDefinedTypeName,
988    ) -> Result<SymbolId> {
989        let mut symbol_id: SymbolId = SymbolId::default();
990        let mut parent_scope = Self::GLOBAL_SCOPE;
991        let mut stacked_names = Vec::new();
992        let last = user_defined_type.len() - 1;
993        for (i, type_part) in user_defined_type.names().iter().enumerate() {
994            stacked_names.push(type_part.to_string());
995            let symbol_kind = if i == last {
996                symbol_kind
997            } else {
998                MetaSymbolKind::Module
999            };
1000            symbol_id = self.get_or_create_type(
1001                type_part,
1002                parent_scope,
1003                TypeEntrails::UserDefinedType(
1004                    symbol_kind,
1005                    UserDefinedTypeName::new(stacked_names.clone()),
1006                ),
1007            )?;
1008            parent_scope = self.symbol_as_type(symbol_id).member_scope();
1009        }
1010        Ok(symbol_id)
1011    }
1012
1013    /// Replace the type of the given instance symbol with the given new type
1014    pub(crate) fn replace_type_of_inst(
1015        &mut self,
1016        inst_symbol_id: SymbolId,
1017        new_type_id: SymbolId,
1018    ) -> Result<()> {
1019        match &mut self[inst_symbol_id].kind {
1020            SymbolKind::Type(_) => panic!("Ain't no instance!"),
1021            SymbolKind::Instance(i) => {
1022                trace!("Replacing type of instance {inst_symbol_id} with type {new_type_id}");
1023                i.type_id = new_type_id
1024            }
1025        };
1026        Ok(())
1027    }
1028
1029    pub(crate) fn replace_wrapped_type(
1030        &mut self,
1031        parent_type: SymbolId,
1032        type_symbol_id: SymbolId,
1033        referred_type_id: SymbolId,
1034    ) -> Result<()> {
1035        debug_assert!(matches!(
1036            self.symbol(type_symbol_id).kind(),
1037            SymbolKind::Type(_)
1038        ));
1039        let parent_scope_id = self.symbol_as_type(parent_type).member_scope();
1040        let parent_scope = self.scope_mut(parent_scope_id);
1041        if parent_scope.symbols.contains(&type_symbol_id) {
1042            self[type_symbol_id].set_inner_type(referred_type_id)?;
1043            // parent_scope.symbols[index] = referred_type_id;
1044        } else {
1045            bail!(
1046                "Type {} not found in scope {}",
1047                type_symbol_id,
1048                parent_scope_id
1049            );
1050        }
1051        Ok(())
1052    }
1053
1054    fn recursive_add_symbols(
1055        &self,
1056        graph: &mut DiGraph<SymbolId, ()>,
1057        node_map: &mut HashMap<SymbolId, NodeIndex>,
1058        symbol: SymbolId,
1059    ) {
1060        // Adds a new node to the graph if it does not exist yet.
1061        fn get_or_add_node(
1062            graph: &mut DiGraph<SymbolId, ()>,
1063            node_map: &mut HashMap<SymbolId, NodeIndex>,
1064            symbol: SymbolId,
1065        ) -> NodeIndex {
1066            if let Some(node_id) = node_map.get(&symbol) {
1067                *node_id
1068            } else {
1069                let node_id = graph.add_node(symbol);
1070                node_map.insert(symbol, node_id);
1071                node_id
1072            }
1073        }
1074        let symbol = &self[symbol];
1075        match &symbol.kind {
1076            SymbolKind::Type(_t) => {
1077                let from_node_id = get_or_add_node(graph, node_map, symbol.my_id);
1078                let type_symbol = self.symbol_as_type(symbol.my_id);
1079                match type_symbol.entrails() {
1080                    TypeEntrails::Surrogate(t)
1081                    | TypeEntrails::EnumVariant(t)
1082                    | TypeEntrails::UserDefinedType(MetaSymbolKind::NonTerminal(t), _)
1083                    | TypeEntrails::Option(t) => {
1084                        // We add an edge from the type to the referred type.
1085                        let to_node_id = get_or_add_node(graph, node_map, *t);
1086                        if graph.find_edge(from_node_id, to_node_id).is_none() {
1087                            graph.add_edge(from_node_id, to_node_id, ());
1088                        } else {
1089                            return;
1090                        }
1091                        self.recursive_add_symbols(graph, node_map, *t);
1092                    }
1093                    TypeEntrails::Struct | TypeEntrails::Enum => {
1094                        // Members of structs are instances. We add an edge from the struct to the
1095                        // instance member.
1096                        // Members of enums are types. We add an edge from the enum to the member.
1097                        for member in self.members(symbol.my_id).unwrap() {
1098                            // These nodes are subject to replacement when removing recursivity.
1099                            let to_node_id = get_or_add_node(graph, node_map, *member);
1100                            if graph.find_edge(from_node_id, to_node_id).is_none() {
1101                                graph.add_edge(from_node_id, to_node_id, ());
1102                            } else {
1103                                return;
1104                            }
1105                            self.recursive_add_symbols(graph, node_map, *member);
1106                        }
1107                    }
1108                    _ => {}
1109                }
1110            }
1111            SymbolKind::Instance(i) => {
1112                let from_node_id = get_or_add_node(graph, node_map, symbol.my_id);
1113                let to_node_id = get_or_add_node(graph, node_map, i.type_id);
1114                if graph.find_edge(from_node_id, to_node_id).is_none() {
1115                    graph.add_edge(from_node_id, to_node_id, ());
1116                } else {
1117                    return;
1118                }
1119                self.recursive_add_symbols(graph, node_map, i.type_id);
1120            }
1121        }
1122    }
1123
1124    /// Find cycles of the types in the symbol table.
1125    pub(crate) fn find_type_cycles(&self) -> Vec<Vec<SymbolId>> {
1126        // First we create a graph of the types. We use the type ids as node ids.
1127        // The edges are the is_used/contains relations between the types.
1128        // We us the petgraph crate to create the graph.
1129        let mut graph = DiGraph::<SymbolId, ()>::new();
1130        let mut node_map: HashMap<SymbolId, NodeIndex> = HashMap::new();
1131
1132        for symbol in &self[SymbolTable::GLOBAL_SCOPE].symbols {
1133            self.recursive_add_symbols(&mut graph, &mut node_map, *symbol);
1134        }
1135        trace!(
1136            "Type graph: \n{:?}",
1137            Dot::with_attr_getters(
1138                &graph,
1139                &[Config::EdgeNoLabel, Config::NodeNoLabel],
1140                &|_, _| { String::default() },
1141                &|_, n| { format!("label = \"{} {}\"", self.name(*n.weight()), n.weight()) }
1142            )
1143        );
1144        if !is_cyclic_directed(&graph) {
1145            // If the graph is acyclic we don't need to remove cycles.
1146            return Vec::new();
1147        }
1148
1149        // Now we find the cycles in the graph.
1150        // Find all strongly connected components
1151        let sccs: Vec<Vec<NodeIndex>> = tarjan_scc(&graph);
1152
1153        // Filter SCCs that contain more than one node (these contain cycles)
1154        sccs.into_iter()
1155            .filter(|scc| scc.len() > 1)
1156            .map(|scc| {
1157                let mut cycle_ids = scc
1158                    .iter()
1159                    .map(|&node_idx| *graph.node_weight(node_idx).unwrap())
1160                    .collect::<Vec<SymbolId>>();
1161                cycle_ids.sort();
1162                cycle_ids
1163            })
1164            .collect::<Vec<Vec<SymbolId>>>()
1165    }
1166
1167    pub(crate) fn remove_recursivity(&mut self) -> Result<()> {
1168        loop {
1169            let cycles = self.find_type_cycles();
1170            if cycles.is_empty() {
1171                break;
1172            }
1173            self.inner_remove_recursivity(cycles)?;
1174        }
1175        Ok(())
1176    }
1177
1178    fn inner_remove_recursivity(&mut self, cycles: Vec<Vec<SymbolId>>) -> Result<()> {
1179        for cycle in cycles {
1180            // We remove the recursivity by modifying the type of the first symbol in the cycle that
1181            // is either a struct member or an EnumVariant. Only these types are used here to remove
1182            // recursivity.
1183            if let Some(symbol_id) = cycle.iter().find(|s| match &self[**s].kind {
1184                SymbolKind::Type(t) => match t.entrails {
1185                    TypeEntrails::EnumVariant(e) => {
1186                        let wrapped_type = self.symbol_as_type(e);
1187                        // And not already boxed
1188                        !matches!(wrapped_type.entrails(), TypeEntrails::Box(_))
1189                    }
1190                    _ => false,
1191                },
1192                SymbolKind::Instance(i) => {
1193                    // Struct member
1194                    let wrapped_type = self.symbol_as_type(i.type_id);
1195                    // And not already boxed
1196                    !matches!(wrapped_type.entrails(), TypeEntrails::Box(_))
1197                }
1198            }) {
1199                let symbol = self[*symbol_id].clone();
1200                match symbol.kind {
1201                    SymbolKind::Type(t) => {
1202                        if let TypeEntrails::EnumVariant(t) = &t.entrails {
1203                            // Create a global boxed type for the recursive type
1204                            let boxed_type = self.get_or_create_type(
1205                                SymbolTable::UNNAMED_TYPE,
1206                                SymbolTable::GLOBAL_SCOPE,
1207                                TypeEntrails::Box(*t),
1208                            )?;
1209                            // Find the parent enum of the enum variant
1210                            let parent_enum = self
1211                                .symbols
1212                                .iter()
1213                                .find(|s| {
1214                                    if let SymbolKind::Type(t) = &s.kind {
1215                                        if matches!(t.entrails, TypeEntrails::Enum) {
1216                                            self.members(s.my_id()).unwrap().contains(symbol_id)
1217                                        } else {
1218                                            false
1219                                        }
1220                                    } else {
1221                                        false
1222                                    }
1223                                })
1224                                .unwrap();
1225                            self.replace_wrapped_type(parent_enum.my_id, *symbol_id, boxed_type)?;
1226                        }
1227                    }
1228                    SymbolKind::Instance(i) => {
1229                        let type_entrails = self.symbol_as_type(i.type_id).entrails().clone();
1230                        if let TypeEntrails::Option(t) = type_entrails {
1231                            let wrapped_type_entrails = self.symbol_as_type(t).entrails().clone();
1232                            if !matches!(wrapped_type_entrails, TypeEntrails::Box(_)) {
1233                                // Create a global boxed type for the recursive type if it is not
1234                                // already boxed
1235                                let boxed_type = self.get_or_create_type(
1236                                    SymbolTable::UNNAMED_TYPE,
1237                                    SymbolTable::GLOBAL_SCOPE,
1238                                    TypeEntrails::Box(t),
1239                                )?;
1240                                let option_of_boxed_type = self.get_or_create_type(
1241                                    SymbolTable::UNNAMED_TYPE,
1242                                    SymbolTable::GLOBAL_SCOPE,
1243                                    TypeEntrails::Option(boxed_type),
1244                                )?;
1245                                self.replace_type_of_inst(*symbol_id, option_of_boxed_type)?;
1246                            }
1247                            // else {
1248                            //     // Replace the type of the struct member with the boxed type
1249                            //     let boxed_type = self.get_or_create_type(
1250                            //         SymbolTable::UNNAMED_TYPE,
1251                            //         SymbolTable::GLOBAL_SCOPE,
1252                            //         TypeEntrails::Box(t),
1253                            //     )?;
1254                            //     self.replace_type_of_inst(*symbol_id, boxed_type)?;
1255                            // }
1256                        } else {
1257                            // Create a global boxed type for the recursive type
1258                            let boxed_type = self.get_or_create_type(
1259                                SymbolTable::UNNAMED_TYPE,
1260                                SymbolTable::GLOBAL_SCOPE,
1261                                TypeEntrails::Box(i.type_id),
1262                            )?;
1263                            // Replace the type of the struct member with the boxed type
1264                            self.replace_type_of_inst(*symbol_id, boxed_type)?;
1265                        }
1266                    }
1267                }
1268            }
1269        }
1270        Ok(())
1271    }
1272}
1273
1274impl Index<SymbolId> for SymbolTable {
1275    type Output = Symbol;
1276
1277    fn index(&self, index: SymbolId) -> &Self::Output {
1278        &self.symbols[index.0]
1279    }
1280}
1281
1282impl IndexMut<SymbolId> for SymbolTable {
1283    fn index_mut(&mut self, index: SymbolId) -> &mut Self::Output {
1284        &mut self.symbols[index.0]
1285    }
1286}
1287
1288impl Index<ScopeId> for SymbolTable {
1289    type Output = Scope;
1290
1291    fn index(&self, index: ScopeId) -> &Self::Output {
1292        &self.scopes[index.0]
1293    }
1294}
1295
1296impl IndexMut<ScopeId> for SymbolTable {
1297    fn index_mut(&mut self, index: ScopeId) -> &mut Self::Output {
1298        &mut self.scopes[index.0]
1299    }
1300}
1301
1302impl Index<ScopedNameId> for SymbolTable {
1303    type Output = str;
1304
1305    fn index(&self, index: ScopedNameId) -> &Self::Output {
1306        &self.scope(index.0).names[index.1]
1307    }
1308}
1309
1310impl IndexMut<ScopedNameId> for SymbolTable {
1311    fn index_mut(&mut self, index: ScopedNameId) -> &mut Self::Output {
1312        &mut self.scope_mut(index.0).names[index.1]
1313    }
1314}
1315
1316impl Display for SymbolTable {
1317    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
1318        writeln!(f, "// Symbols:")?;
1319        for (i, sym) in self.symbols.iter().enumerate() {
1320            writeln!(f, "Sym({}): {}", i, sym.to_rust(self))?;
1321        }
1322        writeln!(f, "// Scopes:")?;
1323        for scope in &self.scopes {
1324            writeln!(f, "{scope}")?;
1325        }
1326        writeln!(f, "// Scope hierarchy:")?;
1327        write!(f, "{}", self.scope(Self::GLOBAL_SCOPE).to_rust(self))
1328    }
1329}
1330
1331#[cfg(test)]
1332mod tests {
1333    use super::*;
1334    #[test]
1335    fn test_scope_relations() {
1336        let mut symbol_table = SymbolTable::new();
1337        // Global scope should have been added automatically in `new`
1338        assert_eq!(1, symbol_table.scopes.len());
1339        // Global scope should have no parent
1340        assert_eq!(None, symbol_table.scope(SymbolTable::GLOBAL_SCOPE).parent);
1341
1342        let struct_id = symbol_table
1343            .insert_global_type("StructA", TypeEntrails::Struct)
1344            .expect("insert_global_type should succeed");
1345        assert_eq!(0, struct_id.0);
1346
1347        // Member scope of new struct should have been added in `insert_global_type`
1348        assert_eq!(2, symbol_table.scopes.len());
1349        // New scope should have global scope as parent
1350        assert_eq!(
1351            Some(SymbolTable::GLOBAL_SCOPE),
1352            symbol_table.scope(ScopeId(1)).parent
1353        );
1354
1355        if let SymbolKind::Type(struct_type) = &symbol_table.symbol(struct_id).kind() {
1356            let symbol = symbol_table.symbol(struct_id);
1357            assert_eq!(0, symbol.my_id().0);
1358            assert_eq!(1, symbol.name_id().1);
1359            assert_eq!(
1360                Some(SymbolTable::GLOBAL_SCOPE),
1361                symbol_table.scope(struct_type.member_scope).parent
1362            );
1363            assert_eq!(1, struct_type.member_scope.0);
1364            // UNNAMED_TYPE's pseudo name '' is already inserted
1365            assert_eq!(1, symbol_table.scope(struct_type.member_scope).names.len());
1366            assert_eq!("StructA", symbol_table.name(symbol.my_id()));
1367        } else {
1368            panic!("StructA should be a type!");
1369        }
1370
1371        let fn_id = symbol_table
1372            .insert_type(
1373                struct_id,
1374                "new",
1375                TypeEntrails::Function(Function::default()),
1376            )
1377            .expect("insert_type should succeed");
1378
1379        if let SymbolKind::Type(struct_type) = &symbol_table.symbol(struct_id).kind() {
1380            assert_eq!(2, symbol_table.scope(struct_type.member_scope).names.len());
1381        } else {
1382            panic!("StructA should be a type!");
1383        }
1384
1385        // Member scope of new function should have been added in `insert_type`
1386        assert_eq!(3, symbol_table.scopes.len());
1387
1388        if let SymbolKind::Type(fn_type) = &symbol_table.symbol(fn_id).kind() {
1389            let symbol = symbol_table.symbol(fn_id);
1390            assert_eq!(1, symbol.my_id().0);
1391            assert_eq!(1, symbol.name_id().1);
1392            assert_eq!(
1393                Some(ScopeId(1)),
1394                symbol_table.scope(fn_type.member_scope).parent
1395            );
1396            assert_eq!(2, fn_type.member_scope.0);
1397            assert_eq!(1, symbol_table.scope(fn_type.member_scope).names.len());
1398            assert_eq!("new", symbol_table.name(symbol.my_id()));
1399        };
1400    }
1401}