swamp_analyzer/
constant.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::err::{Error, ErrorKind};
6use crate::{Analyzer, TypeContext};
7use swamp_semantic::{Constant, ConstantRef, Expression, ExpressionKind};
8
9impl Analyzer<'_> {
10    fn analyze_constant(&mut self, constant: &swamp_ast::ConstantInfo) -> Result<(), Error> {
11        let context = TypeContext::new_anything_argument();
12        let resolved_expr = self.analyze_expression(&constant.expression, &context)?;
13        let resolved_type = resolved_expr.ty.clone();
14        let name_node = self.to_node(&constant.constant_identifier.0);
15        let name_text = self.get_text_resolved(&name_node).to_string();
16        let constant = Constant {
17            name: name_node.clone(),
18            assigned_name: name_text,
19            id: self.shared.state.constants_in_dependency_order.len() as u32,
20            expr: resolved_expr,
21            resolved_type,
22        };
23
24        let const_ref = self
25            .shared
26            .definition_table
27            .add_constant(constant)
28            .map_err(|s| self.create_err_resolved(ErrorKind::SemanticError(s), &name_node))?;
29
30        self.shared
31            .lookup_table
32            .add_constant_link(const_ref.clone())
33            .map_err(|s| self.create_err_resolved(ErrorKind::SemanticError(s), &name_node))?;
34
35        // This extra storage of the constants in modules is to have them in analyze / dependency order
36        self.shared
37            .state
38            .constants_in_dependency_order
39            .push(const_ref);
40
41        Ok(())
42    }
43
44    pub(crate) fn analyze_constant_definition(
45        &mut self,
46        constant: &swamp_ast::ConstantInfo,
47    ) -> Result<(), Error> {
48        self.analyze_constant(constant)
49    }
50
51    pub(crate) fn analyze_constant_access(
52        &self,
53        qualified_constant_identifier: &swamp_ast::QualifiedConstantIdentifier,
54    ) -> Result<Expression, Error> {
55        self.try_find_constant(qualified_constant_identifier)
56            .map_or_else(
57                || {
58                    Err(self.create_err(
59                        ErrorKind::UnknownConstant,
60                        &qualified_constant_identifier.name,
61                    ))
62                },
63                |constant_ref| {
64                    let ty = constant_ref.resolved_type.clone();
65                    Ok(self.create_expr(
66                        ExpressionKind::ConstantAccess(constant_ref.clone()),
67                        ty,
68                        &qualified_constant_identifier.name,
69                    ))
70                },
71            )
72    }
73
74    #[must_use]
75    pub fn try_find_constant(
76        &self,
77        qualified_constant_identifier: &swamp_ast::QualifiedConstantIdentifier,
78    ) -> Option<&ConstantRef> {
79        let path = self.get_module_path(qualified_constant_identifier.module_path.as_ref());
80        let constant_name = self.get_text(&qualified_constant_identifier.name);
81
82        let maybe_symbol_table = self.shared.get_symbol_table(&path);
83        maybe_symbol_table.map_or_else(
84            || None,
85            |symbol_table| Some(symbol_table.get_constant(constant_name)),
86        )?
87    }
88}