Skip to main content

microcad_lang/parse/
use.rs

1// Copyright © 2025-2026 The µcad authors <info@microcad.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                UseStatementPart::Error(_) => None,
34            })
35            .collect::<Result<Vec<_>, _>>()?;
36        let name = QualifiedName::new(name, context.src_ref(&node.name.span));
37
38        let decl = match (glob_index.is_some(), &node.use_as) {
39            (false, None) => UseDeclaration::Use(name),
40            (true, None) => UseDeclaration::UseAll(name),
41            (true, Some(_)) => {
42                return Err(ParseError::UseGlobAlias(context.src_ref(&node.span)));
43            }
44            (false, Some(alias)) => {
45                UseDeclaration::UseAs(name, Identifier::from_ast(alias, context)?)
46            }
47        };
48        let visibility = node
49            .visibility
50            .as_ref()
51            .map(|visibility| Visibility::from_ast(visibility, context))
52            .transpose()?;
53        Ok(UseStatement {
54            keyword_ref: context.src_ref(&node.keyword_span),
55            src_ref: context.src_ref(&node.span),
56            visibility: visibility.unwrap_or_default(),
57            decl,
58        })
59    }
60}
61
62impl FromAst for Visibility {
63    type AstNode = ast::Visibility;
64
65    fn from_ast(node: &Self::AstNode, _context: &ParseContext) -> Result<Self, ParseError> {
66        Ok(match node {
67            ast::Visibility::Public => Self::Public,
68        })
69    }
70}