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 Context) -> EvalResult<()> {
42        context.grant(self)?;
43        log::debug!("Evaluating use statement: {self}");
44        if matches!(self.decl, UseDeclaration::UseAll(..)) || self.visibility == Visibility::Private
45        {
46            self.decl.eval(context)
47        } else {
48            Ok(())
49        }
50    }
51}
52
53impl Eval<()> for UseDeclaration {
54    fn eval(&self, context: &mut Context) -> EvalResult<()> {
55        match &self {
56            UseDeclaration::Use(visibility, name) => {
57                if let Err(err) = context.use_symbol(*visibility, name, None) {
58                    context.error(name, err)?;
59                }
60            }
61            UseDeclaration::UseAll(visibility, name) => {
62                if let Err(err) = context.use_symbols_of(*visibility, name) {
63                    context.error(name, err)?
64                }
65            }
66            UseDeclaration::UseAlias(visibility, name, alias) => {
67                if let Err(err) = context.use_symbol(*visibility, name, Some(alias.clone())) {
68                    context.error(name, err)?;
69                }
70            }
71        };
72        Ok(())
73    }
74}