1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright (c) 2016-2020 Fabian Schuiki

use crate::hir::prelude::*;

use crate::common::name::{get_name_table, Name};
use crate::common::score::Result;
use crate::common::source::{Span, Spanned, INVALID_SPAN};

use crate::arenas::Alloc;
use crate::hir::visit::Visitor;
use crate::hir::{FromAst, LatentNode, Node, Package2};
use crate::scope2::{Def2, ScopeContext, ScopeData};
use crate::syntax::ast;

/// A library.
#[derive(Debug)]
pub struct Library<'t> {
    name: Name,
    units: Vec<&'t LatentNode<'t, Node<'t>>>,
    scope: &'t ScopeData<'t>,
}

impl<'t> Library<'t> {
    /// Create a new library of design units.
    pub fn new(
        name: Name,
        units: &[&'t ast::DesignUnit],
        ctx: AllocContext<'t>,
    ) -> Result<&'t Library<'t>> {
        let ctx = ctx.create_subscope();
        let units = units
            .into_iter()
            .flat_map(|unit| -> Option<&'t LatentNode<'t, Node<'t>>> {
                match unit.data {
                    ast::DesignUnitData::PkgDecl(ref decl) => {
                        Some(Package2::alloc_slot(decl, ctx).ok()?)
                    }
                    _ => None,
                }
            })
            .collect();
        let lib = ctx.alloc(Library {
            name: name,
            units: units,
            scope: ctx.scope(),
        });
        ctx.define(
            Spanned::new(get_name_table().intern("WORK", false).into(), INVALID_SPAN),
            Def2::Lib(lib),
        )?;
        Ok(lib)
    }

    /// Return the name of the library.
    pub fn name(&self) -> Name {
        self.name
    }

    /// Return a slice of the design units in this library.
    pub fn units(&self) -> &[&'t LatentNode<'t, Node<'t>>] {
        &self.units
    }

    /// Return the scope of the library.
    pub fn scope(&self) -> &'t ScopeData<'t> {
        self.scope
    }
}

impl<'t> Node<'t> for Library<'t> {
    fn span(&self) -> Span {
        INVALID_SPAN
    }

    fn desc_kind(&self) -> String {
        "library".into()
    }

    fn desc_name(&self) -> String {
        format!("library `{}`", self.name)
    }

    fn accept(&'t self, visitor: &mut Visitor<'t>) {
        visitor.visit_library(self);
    }

    fn walk(&'t self, visitor: &mut Visitor<'t>) {
        for u in &self.units {
            u.accept(visitor);
        }
    }
}