1use crate::TypeContext;
6use crate::{Analyzer, LocationSide};
7use source_map_node::Node;
8use swamp_semantic::err::ErrorKind;
9use swamp_semantic::{ArgumentExpression, Expression, ExpressionKind};
10use swamp_types::prelude::*;
11
12pub struct MaybeBorrowMutRefExpression {
13 pub ast_expression: swamp_ast::Expression,
14 pub has_borrow_mutable_reference: Option<Node>,
15}
16
17impl Analyzer<'_> {
18 pub fn analyze_argument(
31 &mut self,
32 fn_parameter: &TypeForParameter,
33 argument_expr: &swamp_ast::Expression,
34 ) -> ArgumentExpression {
35 let context = TypeContext::new_argument(
36 &fn_parameter.resolved_type,
37 false, );
39
40 let ref_checked_argument = self.analyze_maybe_ref_expression(argument_expr);
41
42 if fn_parameter.is_mutable {
43 if ref_checked_argument.has_borrow_mutable_reference.is_none() {
44 let expr = self.create_err(ErrorKind::ArgumentIsNotMutable, &argument_expr.node);
46 return ArgumentExpression::Expression(expr);
47 }
48 let mut_location = self.analyze_to_location(
49 &ref_checked_argument.ast_expression,
50 &context,
51 LocationSide::Rhs,
52 );
53
54 ArgumentExpression::BorrowMutableReference(mut_location)
55 } else {
56 if ref_checked_argument.has_borrow_mutable_reference.is_some() {
57 {
58 let expr =
59 self.create_err(ErrorKind::ParameterIsNotMutable, &argument_expr.node);
60 return ArgumentExpression::Expression(expr);
62 }
63 }
64
65 let resolved_expr = self.analyze_expression(&ref_checked_argument.ast_expression, &context.with_ephemeral());
66 if self.needs_materialization(&resolved_expr) {
68 if resolved_expr.ty.is_blittable() {
70 ArgumentExpression::MaterializedExpression(resolved_expr)
71 } else {
72 ArgumentExpression::Expression(self.create_err(ErrorKind::CanNotCreateTemporaryStorage, &argument_expr.node))
74 }
75 } else {
76 ArgumentExpression::Expression(resolved_expr)
77 }
78 }
79 }
80
81 pub fn analyze_and_verify_parameters(
84 &mut self,
85 node: &swamp_ast::Node,
86 fn_parameters: &[TypeForParameter],
87 arguments: &[swamp_ast::Expression],
88 ) -> Vec<ArgumentExpression> {
89 if fn_parameters.len() != arguments.len() {
90 self.add_err(
91 ErrorKind::WrongNumberOfArguments(fn_parameters.len(), arguments.len()),
92 node,
93 );
94 return vec![];
95 }
96
97 if fn_parameters.len() > Self::MAX_PARAMETER_COUNT {
98 self.add_err(
99 ErrorKind::TooManyParameters {
100 encountered: fn_parameters.len(),
101 allowed: Self::MAX_PARAMETER_COUNT,
102 },
103 node,
104 );
105 return vec![];
106 }
107
108 let mut resolved_arguments = Vec::new();
109 for (fn_parameter, argument_expr) in fn_parameters.iter().zip(arguments) {
110 let mut_or_immutable = self.analyze_argument(fn_parameter, argument_expr);
111 resolved_arguments.push(mut_or_immutable);
112 }
113
114 resolved_arguments
115 }
116
117 pub fn analyze_mut_or_immutable_expression(
120 &mut self,
121 expr: &swamp_ast::Expression,
122 context: &TypeContext,
123 location_side: LocationSide,
124 ) -> ArgumentExpression {
125 let maybe_borrow_or_normal_expression = self.analyze_maybe_ref_expression(expr);
126
127 if maybe_borrow_or_normal_expression
128 .has_borrow_mutable_reference
129 .is_some()
130 {
131 ArgumentExpression::BorrowMutableReference(self.analyze_to_location(
132 &maybe_borrow_or_normal_expression.ast_expression,
133 context,
134 location_side,
135 ))
136 } else {
137 ArgumentExpression::Expression(
138 self.analyze_expression(&maybe_borrow_or_normal_expression.ast_expression, context),
139 )
140 }
141 }
142
143 const fn needs_materialization(&self, expr: &Expression) -> bool {
180 match &expr.kind {
181 ExpressionKind::ConstantAccess(_) => false,
182 ExpressionKind::VariableAccess(_) => false,
183 ExpressionKind::BinaryOp(_) => true,
184 ExpressionKind::UnaryOp(_) => true,
185 ExpressionKind::PostfixChain(_, _) => false,
186 ExpressionKind::CoerceOptionToBool(_) => false,
187 ExpressionKind::CoerceIntToChar(_) => false,
188 ExpressionKind::CoerceIntToByte(_) => false,
189 ExpressionKind::CoerceToAny(_) => true,
190 ExpressionKind::IntrinsicCallEx(_, _) => true,
191 ExpressionKind::InternalCall(_, _) => true,
192 ExpressionKind::HostCall(_, _) => true,
193 ExpressionKind::VariableDefinition(_, _) => true,
194 ExpressionKind::VariableDefinitionLValue(_, _) => true,
195 ExpressionKind::VariableReassignment(_, _) => true,
196 ExpressionKind::Assignment(_, _) => true,
197 ExpressionKind::CompoundAssignment(_, _, _) => true,
198 ExpressionKind::AnonymousStructLiteral(_) => true,
199 ExpressionKind::NamedStructLiteral(_) => true,
200 ExpressionKind::FloatLiteral(_) => true,
201 ExpressionKind::NoneLiteral => true,
202 ExpressionKind::IntLiteral(_) => true,
203 ExpressionKind::ByteLiteral(_) => true,
204 ExpressionKind::StringLiteral(_) => true,
205 ExpressionKind::BoolLiteral(_) => true,
206 ExpressionKind::EnumVariantLiteral(_, _) => true,
207 ExpressionKind::TupleLiteral(_) => true,
208 ExpressionKind::InitializerList(_, _) => true,
209 ExpressionKind::InitializerPairList(_, _) => true,
210 ExpressionKind::Option(_) => true,
211 ExpressionKind::ForLoop(_, _, _) => true,
212 ExpressionKind::WhileLoop(_, _) => true,
213 ExpressionKind::Block(_) => true,
214 ExpressionKind::Match(_) => true,
215 ExpressionKind::Guard(_) => true,
216 ExpressionKind::If(_, _, _) => true,
217 ExpressionKind::When(_, _, _) => true,
218 ExpressionKind::TupleDestructuring(_, _, _) => true,
219 ExpressionKind::Lambda(_, _) => false,
220 ExpressionKind::BorrowMutRef(_) => true,
221 ExpressionKind::Error(_) => true,
222 }
223 }
224}