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