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