swamp_script_analyzer/
call.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::TypeContext;
7use crate::err::{Error, ErrorKind};
8use crate::{Analyzer, LocationSide, SPARSE_TYPE_ID};
9use std::rc::Rc;
10use swamp_script_node::Node;
11use swamp_script_semantic::intr::IntrinsicFunction;
12use swamp_script_semantic::{
13    ArgumentExpressionOrLocation, Expression, ExpressionKind, MutOrImmutableExpression,
14};
15use swamp_script_types::prelude::*;
16
17impl Analyzer<'_> {
18    /// # Errors
19    ///
20    pub fn analyze_argument(
21        &mut self,
22        fn_parameter: &TypeForParameter,
23        argument_expr: &swamp_script_ast::MutableOrImmutableExpression,
24    ) -> Result<ArgumentExpressionOrLocation, Error> {
25        let context = TypeContext::new_argument(&fn_parameter.resolved_type);
26
27        let mut_or_immutable = if fn_parameter.is_mutable {
28            if argument_expr.is_mutable.is_none() {
29                return Err(self.create_err(
30                    ErrorKind::ArgumentIsNotMutable,
31                    &argument_expr.expression.node,
32                ));
33            }
34            let mut_location =
35                self.analyze_to_location(&argument_expr.expression, &context, LocationSide::Rhs)?;
36            ArgumentExpressionOrLocation::Location(mut_location)
37        } else {
38            if argument_expr.is_mutable.is_some() {
39                return Err(self.create_err(
40                    ErrorKind::ParameterIsNotMutable,
41                    &argument_expr.expression.node,
42                ));
43            }
44            let resolved_expr = self.analyze_expression(&argument_expr.expression, &context)?;
45            ArgumentExpressionOrLocation::Expression(resolved_expr)
46        };
47
48        Ok(mut_or_immutable)
49    }
50
51    /// # Errors
52    ///
53    pub fn analyze_and_verify_parameters(
54        &mut self,
55        node: &Node,
56        fn_parameters: &[TypeForParameter],
57        arguments: &[swamp_script_ast::MutableOrImmutableExpression],
58    ) -> Result<Vec<ArgumentExpressionOrLocation>, Error> {
59        if fn_parameters.len() != arguments.len() {
60            return Err(self.create_err_resolved(
61                ErrorKind::WrongNumberOfArguments(fn_parameters.len(), arguments.len()),
62                node,
63            ));
64        }
65
66        let mut resolved_arguments = Vec::new();
67        for (fn_parameter, argument_expr) in fn_parameters.iter().zip(arguments) {
68            let mut_or_immutable = self.analyze_argument(fn_parameter, argument_expr)?;
69            resolved_arguments.push(mut_or_immutable);
70        }
71
72        Ok(resolved_arguments)
73    }
74
75    pub(crate) fn check_for_internal_static_call(
76        &mut self,
77        type_name: &swamp_script_ast::QualifiedTypeIdentifier,
78        function_name: &swamp_script_ast::Node,
79        arguments: &[swamp_script_ast::MutableOrImmutableExpression],
80    ) -> Result<Option<Expression>, Error> {
81        let (type_name_text, function_name_text) = {
82            (
83                self.get_text(&type_name.name.0).to_string(),
84                self.get_text(function_name).to_string(),
85            )
86        };
87
88        if !type_name.generic_params.is_empty() {
89            let resolved_generic_type_parameters = self.analyze_types(&type_name.generic_params)?;
90
91            if type_name_text == "Sparse" && function_name_text == "new" {
92                if !arguments.is_empty() {
93                    return Err(self.create_err(
94                        ErrorKind::WrongNumberOfArguments(arguments.len(), 0),
95                        function_name,
96                    ));
97                }
98                if resolved_generic_type_parameters.len() != 1 {
99                    return Err(self.create_err(
100                        ErrorKind::WrongNumberOfTypeArguments(
101                            resolved_generic_type_parameters.len(),
102                            1,
103                        ),
104                        function_name,
105                    ));
106                }
107
108                let rust_type_ref = Rc::new(ExternalType {
109                    type_name: type_name_text,
110                    number: SPARSE_TYPE_ID, // TODO: FIX hardcoded number
111                });
112
113                let rust_type_base = Type::External(rust_type_ref.clone());
114
115                let generic_specific_type = Type::Generic(
116                    Box::from(rust_type_base.clone()),
117                    resolved_generic_type_parameters.clone(),
118                );
119
120                let value_item_type = resolved_generic_type_parameters[0].clone();
121
122                let expr = self.create_expr(
123                    ExpressionKind::IntrinsicCallGeneric(
124                        IntrinsicFunction::SparseNew,
125                        resolved_generic_type_parameters,
126                        vec![],
127                    ),
128                    generic_specific_type,
129                    &type_name.name.0,
130                );
131
132                return Ok(Some(expr));
133            }
134        }
135
136        Ok(None)
137    }
138
139    /// # Errors
140    ///
141    pub fn analyze_mut_or_immutable_expression(
142        &mut self,
143        expr: &swamp_script_ast::MutableOrImmutableExpression,
144        context: &TypeContext,
145        location_side: LocationSide,
146    ) -> Result<MutOrImmutableExpression, Error> {
147        let is_mutable = self.to_node_option(Option::from(&expr.is_mutable));
148        let expression_or_location = if is_mutable.is_some() {
149            ArgumentExpressionOrLocation::Location(self.analyze_to_location(
150                &expr.expression,
151                context,
152                location_side,
153            )?)
154        } else {
155            ArgumentExpressionOrLocation::Expression(
156                self.analyze_expression(&expr.expression, context)?,
157            )
158        };
159
160        Ok(MutOrImmutableExpression {
161            expression_or_location,
162            is_mutable,
163        })
164    }
165}