swamp_script_analyzer/
access.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 */
5use crate::Analyzer;
6use crate::TypeContext;
7use crate::err::{Error, ErrorKind};
8use swamp_script_semantic::{Expression, ExpressionKind, Function, FunctionRef, Range, RangeMode};
9use swamp_script_types::prelude::*;
10
11impl Analyzer<'_> {
12    #[must_use]
13    pub fn convert_to_function_access_kind(function_ref: &FunctionRef) -> ExpressionKind {
14        match &**function_ref {
15            Function::Internal(internal_function) => {
16                ExpressionKind::InternalFunctionAccess(internal_function.clone())
17            }
18            Function::External(external_function) => {
19                ExpressionKind::ExternalFunctionAccess(external_function.clone())
20            }
21        }
22    }
23
24    #[must_use]
25    pub fn lookup_associated_function(
26        &self,
27        ty: &Type,
28        function_name: &str,
29    ) -> Option<FunctionRef> {
30        self.shared
31            .state
32            .associated_impls
33            .get_member_function(ty, function_name)
34            .cloned()
35    }
36
37    #[must_use]
38    pub fn convert_to_function_access_expr(
39        &self,
40        associated_function_info: &FunctionRef,
41        ast_node: &swamp_script_ast::Node,
42    ) -> Expression {
43        let kind = Self::convert_to_function_access_kind(associated_function_info);
44        self.create_expr(
45            kind,
46            Type::Function(associated_function_info.signature().clone()),
47            ast_node,
48        )
49    }
50
51    pub(crate) fn analyze_static_member_access(
52        &mut self,
53        named_type: &swamp_script_ast::QualifiedTypeIdentifier,
54        member_name_node: &swamp_script_ast::Node,
55    ) -> Result<Expression, Error> {
56        let some_type = self.analyze_named_type(named_type)?;
57        let member_name = self.get_text(member_name_node);
58        self.lookup_associated_function(&some_type, member_name)
59            .map_or_else(
60                || Err(self.create_err(ErrorKind::UnknownMemberFunction, member_name_node)),
61                |member_function| {
62                    let expr =
63                        self.convert_to_function_access_expr(&member_function, member_name_node);
64                    Ok(expr)
65                },
66            )
67    }
68
69    pub(crate) fn analyze_min_max_expr(
70        &mut self,
71        min_expr: &swamp_script_ast::Expression,
72        max_expr: &swamp_script_ast::Expression,
73    ) -> Result<(Expression, Expression), Error> {
74        let context = TypeContext::new_argument(&Type::Int);
75
76        let resolved_min = self.analyze_expression(min_expr, &context)?;
77        let resolved_max = self.analyze_expression(max_expr, &context)?;
78
79        Ok((resolved_min, resolved_max))
80    }
81
82    /// # Errors
83    ///
84    pub fn analyze_range(
85        &mut self,
86        min_expr: &swamp_script_ast::Expression,
87        max_expr: &swamp_script_ast::Expression,
88        mode: &swamp_script_ast::RangeMode,
89    ) -> Result<Range, Error> {
90        let (min, max) = self.analyze_min_max_expr(min_expr, max_expr)?;
91
92        let resolved_range_mode = match mode {
93            swamp_script_ast::RangeMode::Inclusive => RangeMode::Inclusive,
94            swamp_script_ast::RangeMode::Exclusive => RangeMode::Exclusive,
95        };
96        Ok(Range {
97            min,
98            max,
99            mode: resolved_range_mode,
100        })
101    }
102
103    /// # Errors
104    ///
105    pub fn analyze_string_range_access(
106        &mut self,
107        base_expr: Expression,
108        range: Range,
109    ) -> Result<Expression, Error> {
110        let ty = base_expr.ty.clone();
111        let node = base_expr.node.clone();
112        Ok(self.create_expr_resolved(
113            ExpressionKind::StringRangeAccess(Box::from(base_expr), Box::from(range)),
114            ty,
115            &node,
116        ))
117    }
118}