microcad_lang/eval/statements/
use_statement.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::eval::*;
5
6/// Trait used by [UseDeclaration] and implemented by [SymbolTable] and passed through by [Context]
7/// to put symbols on the [Stack] (for `use statements`).
8pub trait UseSymbol {
9    /// Find a symbol in the symbol table and copy it to the locals.
10    ///
11    /// Might load any related external file if not already loaded.
12    ///
13    /// # Arguments
14    /// - `name`: Name of the symbol to search for
15    /// - `id`: if given overwrites the ID from qualified name (use as)
16    /// - `within`: Target symbol
17    fn use_symbol(
18        &mut self,
19        visibility: Visibility,
20        name: &QualifiedName,
21        id: Option<Identifier>,
22        within: &QualifiedName,
23    ) -> EvalResult<Symbol>;
24
25    /// Find a symbol in the symbol table and copy all it's children to the locals and the target.
26    ///
27    /// Might load any related external file if not already loaded.
28    ///
29    /// # Arguments
30    /// - `name`: Name of the symbol to search for
31    /// - `within`: Target symbol
32    fn use_symbols_of(
33        &mut self,
34        visibility: Visibility,
35        name: &QualifiedName,
36        within: &QualifiedName,
37    ) -> EvalResult<Symbol>;
38}
39
40impl Eval<()> for UseStatement {
41    fn eval(&self, context: &mut EvalContext) -> EvalResult<()> {
42        context.grant(self)?;
43
44        if !context.is_module() {
45            log::trace!("Evaluating use statement: {self}");
46            let current = &context.current_name();
47            let visibility = self.visibility;
48            match &self.decl {
49                UseDeclaration::Use(name) => {
50                    let mut symbol = context.lookup(name)?;
51                    symbol.set_visibility(visibility);
52                    if let Err(err) = context.add_symbol(symbol.id(), symbol) {
53                        context.error(name, err)?;
54                    }
55                }
56                UseDeclaration::UseAll(name) => {
57                    if let Err(err) = context.use_symbols_of(visibility, name, current) {
58                        context.error(name, err)?
59                    }
60                }
61                UseDeclaration::UseAlias(name, alias) => {
62                    if let Err(err) =
63                        context.use_symbol(visibility, name, Some(alias.clone()), current)
64                    {
65                        context.error(name, err)?;
66                    }
67                }
68            }
69        }
70        Ok(())
71    }
72}