Skip to main content

microcad_lang/parse/
use.rs

1// Copyright © 2025-2026 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{parse::*, parser::*, syntax::*};
5use microcad_syntax::ast;
6use microcad_syntax::ast::UseStatementPart;
7
8impl FromAst for UseStatement {
9    type AstNode = ast::UseStatement;
10
11    fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
12        let glob_index = node
13            .name
14            .parts
15            .iter()
16            .enumerate()
17            .find(|(_, part)| matches!(part, UseStatementPart::Glob(_)))
18            .map(|(i, _)| i);
19        if let Some(i) = glob_index {
20            if i < node.name.parts.len() - 1 {
21                return Err(ParseError::InvalidGlobPattern(
22                    context.src_ref(&node.name.span),
23                ));
24            }
25        }
26        let name = node
27            .name
28            .parts
29            .iter()
30            .filter_map(|part| match part {
31                UseStatementPart::Identifier(ident) => Some(Identifier::from_ast(ident, context)),
32                UseStatementPart::Glob(_) => None,
33            })
34            .collect::<Result<Vec<_>, _>>()?;
35        let name = QualifiedName::new(name, context.src_ref(&node.name.span));
36
37        let decl = match (glob_index.is_some(), &node.use_as) {
38            (false, None) => UseDeclaration::Use(name),
39            (true, None) => UseDeclaration::UseAll(name),
40            (true, Some(_)) => {
41                return Err(ParseError::UseGlobAlias(context.src_ref(&node.span)));
42            }
43            (false, Some(alias)) => {
44                UseDeclaration::UseAs(name, Identifier::from_ast(alias, context)?)
45            }
46        };
47        let visibility = node
48            .visibility
49            .as_ref()
50            .map(|visibility| Visibility::from_ast(visibility, context))
51            .transpose()?;
52        Ok(UseStatement {
53            src_ref: context.src_ref(&node.span),
54            visibility: visibility.unwrap_or_default(),
55            decl,
56        })
57    }
58}
59
60impl FromAst for Visibility {
61    type AstNode = ast::Visibility;
62
63    fn from_ast(node: &Self::AstNode, _context: &ParseContext) -> Result<Self, ParseError> {
64        Ok(match node {
65            ast::Visibility::Public => Self::Public,
66        })
67    }
68}