swamp_script_analyzer/
constant.rs

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