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(
66 &ref_checked_argument.ast_expression,
67 &context.with_ephemeral(),
68 );
69 if self.needs_materialization(&resolved_expr) {
71 if resolved_expr.ty.can_be_materialized() {
73 ArgumentExpression::MaterializedExpression(resolved_expr)
74 } else {
75 ArgumentExpression::Expression(
77 self.create_err(
78 ErrorKind::CanNotCreateTemporaryStorage,
79 &argument_expr.node,
80 ),
81 )
82 }
83 } else {
84 ArgumentExpression::Expression(resolved_expr)
85 }
86 }
87 }
88
89 pub fn analyze_and_verify_parameters(
92 &mut self,
93 node: &swamp_ast::Node,
94 fn_parameters: &[TypeForParameter],
95 arguments: &[swamp_ast::Expression],
96 ) -> Vec<ArgumentExpression> {
97 if fn_parameters.len() != arguments.len() {
98 self.add_err(
99 ErrorKind::WrongNumberOfArguments(fn_parameters.len(), arguments.len()),
100 node,
101 );
102 return vec![];
103 }
104
105 if fn_parameters.len() > Self::MAX_PARAMETER_COUNT {
106 self.add_err(
107 ErrorKind::TooManyParameters {
108 encountered: fn_parameters.len(),
109 allowed: Self::MAX_PARAMETER_COUNT,
110 },
111 node,
112 );
113 return vec![];
114 }
115
116 let mut resolved_arguments = Vec::new();
117 for (fn_parameter, argument_expr) in fn_parameters.iter().zip(arguments) {
118 let mut_or_immutable = self.analyze_argument(fn_parameter, argument_expr);
119 resolved_arguments.push(mut_or_immutable);
120 }
121
122 resolved_arguments
123 }
124
125 pub fn analyze_mut_or_immutable_expression(
128 &mut self,
129 expr: &swamp_ast::Expression,
130 context: &TypeContext,
131 location_side: LocationSide,
132 ) -> ArgumentExpression {
133 let maybe_borrow_or_normal_expression = self.analyze_maybe_ref_expression(expr);
134
135 if maybe_borrow_or_normal_expression
136 .has_borrow_mutable_reference
137 .is_some()
138 {
139 ArgumentExpression::BorrowMutableReference(self.analyze_to_location(
140 &maybe_borrow_or_normal_expression.ast_expression,
141 context,
142 location_side,
143 ))
144 } else {
145 ArgumentExpression::Expression(
146 self.analyze_expression(&maybe_borrow_or_normal_expression.ast_expression, context),
147 )
148 }
149 }
150
151 const fn needs_materialization(&self, expr: &Expression) -> bool {
188 match &expr.kind {
189 ExpressionKind::ConstantAccess(_) => false,
190 ExpressionKind::VariableAccess(_) => false,
191 ExpressionKind::BinaryOp(_) => true,
192 ExpressionKind::UnaryOp(_) => true,
193 ExpressionKind::PostfixChain(_, _) => true,
194 ExpressionKind::CoerceOptionToBool(_) => false,
195 ExpressionKind::CoerceIntToChar(_) => false,
196 ExpressionKind::CoerceIntToByte(_) => false,
197 ExpressionKind::CoerceToAny(_) => true,
198 ExpressionKind::IntrinsicCallEx(_, _) => true,
199 ExpressionKind::InternalCall(_, _) => true,
200 ExpressionKind::HostCall(_, _) => true,
201 ExpressionKind::VariableDefinition(_, _) => true,
202 ExpressionKind::VariableDefinitionLValue(_, _) => true,
203 ExpressionKind::VariableReassignment(_, _) => true,
204 ExpressionKind::Assignment(_, _) => true,
205 ExpressionKind::CompoundAssignment(_, _, _) => true,
206 ExpressionKind::AnonymousStructLiteral(_) => true,
207 ExpressionKind::NamedStructLiteral(_) => true,
208 ExpressionKind::FloatLiteral(_) => true,
209 ExpressionKind::NoneLiteral => true,
210 ExpressionKind::IntLiteral(_) => true,
211 ExpressionKind::ByteLiteral(_) => true,
212 ExpressionKind::StringLiteral(_) => true,
213 ExpressionKind::BoolLiteral(_) => true,
214 ExpressionKind::EnumVariantLiteral(_, _) => true,
215 ExpressionKind::TupleLiteral(_) => true,
216 ExpressionKind::InitializerList(_, _) => true,
217 ExpressionKind::InitializerPairList(_, _) => true,
218 ExpressionKind::Option(_) => true,
219 ExpressionKind::ForLoop(_, _, _) => true,
220 ExpressionKind::WhileLoop(_, _) => true,
221 ExpressionKind::Block(_) => true,
222 ExpressionKind::Match(_) => true,
223 ExpressionKind::Guard(_) => true,
224 ExpressionKind::If(_, _, _) => true,
225 ExpressionKind::When(_, _, _) => true,
226 ExpressionKind::TupleDestructuring(_, _, _) => true,
227 ExpressionKind::Lambda(_, _) => false,
228 ExpressionKind::BorrowMutRef(_) => true,
229 ExpressionKind::Error(_) => true,
230 }
231 }
232}