swamp_script_analyzer/
call.rs1use 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 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 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, });
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 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}