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