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