1pub mod access;
6pub mod call;
7pub mod constant;
8pub mod def;
9pub mod err;
10pub mod literal;
11pub mod operator;
12pub mod pattern;
13pub mod prelude;
14mod structure;
15pub mod types;
16pub mod variable;
17
18use crate::call::MaybeBorrowMutRefExpression;
19use crate::err::{Error, ErrorKind};
20use seq_map::SeqMap;
21use source_map_cache::SourceMap;
22use source_map_node::{FileId, Node, Span};
23use std::mem::take;
24use std::num::{ParseFloatError, ParseIntError};
25use std::ops::Deref;
26use std::task::Context;
27use swamp_modules::prelude::*;
28use swamp_modules::symtbl::{SymbolTableRef, TypeGeneratorKind};
29use swamp_semantic::instantiator::TypeVariableScope;
30use swamp_semantic::prelude::*;
31use swamp_semantic::type_var_stack::SemanticContext;
32use swamp_semantic::{
33 BlockScope, BlockScopeMode, FunctionScopeState, InternalMainExpression, LocationAccess,
34 LocationAccessKind, MutRefOrImmutableExpression, MutableReferenceKind, NormalPattern, Postfix,
35 PostfixKind, SingleLocationExpression, TargetAssignmentLocation, TypeWithMut, WhenBinding,
36};
37use swamp_types::all_types_are_concrete_or_unit;
38use swamp_types::prelude::*;
39use tracing::info;
40
41#[derive(Copy, Clone, Eq, PartialEq, Debug)]
42pub enum LocationSide {
43 Lhs,
44 Rhs,
45}
46
47#[derive(Debug)]
48pub struct Program {
49 pub state: ProgramState,
50 pub modules: Modules,
51 pub default_symbol_table: SymbolTable,
52}
53
54impl Default for Program {
55 fn default() -> Self {
56 Self::new(ProgramState::new(), Modules::new(), SymbolTable::new(&[]))
57 }
58}
59
60impl Program {
61 #[must_use]
62 pub const fn new(
63 state: ProgramState,
64 modules: Modules,
65 default_symbol_table: SymbolTable,
66 ) -> Self {
67 Self {
68 state,
69 modules,
70 default_symbol_table,
71 }
72 }
73}
74
75#[must_use]
76pub const fn convert_span(without: &swamp_ast::SpanWithoutFileId, file_id: FileId) -> Span {
77 Span {
78 file_id,
79 offset: without.offset,
80 length: without.length,
81 }
82}
83
84#[derive(Debug, Clone)]
86pub struct TypeContext<'a> {
87 pub expected_type: Option<&'a Type>,
89}
90
91impl<'a> TypeContext<'a> {
92 #[must_use]
93 pub const fn new(expected_type: Option<&'a Type>) -> Self {
94 Self { expected_type }
95 }
96
97 #[must_use]
98 pub const fn new_argument(required_type: &'a Type) -> Self {
99 Self {
100 expected_type: Some(required_type),
101 }
102 }
103
104 #[must_use]
105 pub const fn new_unsure_argument(expected_type: Option<&'a Type>) -> Self {
106 Self { expected_type }
107 }
108
109 #[must_use]
110 pub const fn new_anything_argument() -> Self {
111 Self {
112 expected_type: None,
113 }
114 }
115
116 #[must_use]
117 pub const fn new_function(required_type: &'a Type) -> Self {
118 Self {
119 expected_type: Some(required_type),
120 }
121 }
122
123 #[must_use]
124 pub const fn with_expected_type(&self, expected_type: Option<&'a Type>) -> Self {
125 Self { expected_type }
126 }
127
128 pub(crate) const fn we_know_expected_type(&self, found_type: &'a Type) -> Self {
129 self.with_expected_type(Some(found_type))
130 }
131}
132
133pub struct SharedState<'a> {
134 pub state: &'a mut ProgramState,
135 pub lookup_table: SymbolTable,
136 pub definition_table: SymbolTable,
137 pub modules: &'a Modules,
138 pub source_map: &'a SourceMap,
139 pub file_id: FileId,
140 pub core_symbol_table: SymbolTableRef,
141 pub type_variables: SemanticContext,
142}
143
144impl<'a> SharedState<'a> {
145 #[must_use]
146 pub fn get_symbol_table(&'a self, path: &[String]) -> Option<&'a SymbolTable> {
147 if path.is_empty() {
148 return Some(&self.lookup_table);
149 }
150 self.get_module(path).map(|module| &module.symbol_table)
151 }
152
153 #[must_use]
154 pub fn get_module(&'a self, path: &[String]) -> Option<&'a ModuleRef> {
155 let resolved_path = {
156 self.lookup_table.get_package_version(&path[0]).map_or_else(
157 || path.to_vec(),
158 |found_version| {
159 let mut new_path = path.to_vec();
160 let complete_name = format!("{}-{found_version}", path[0]);
161 new_path[0] = complete_name;
162 new_path
163 },
165 )
166 };
167
168 if path.len() == 1 {
169 if let Some(module_ref) = self.lookup_table.get_module_link(&path[0]) {
170 return Some(module_ref);
171 }
172 }
173
174 if let Some(x) = self.modules.get(&resolved_path) {
175 return Some(x);
176 }
177
178 None
179 }
180}
181
182pub struct Analyzer<'a> {
183 pub shared: SharedState<'a>,
184 scope: FunctionScopeState,
185 function_variables: Vec<VariableRef>,
186 global: FunctionScopeState,
187 module_path: Vec<String>,
188}
189
190impl Analyzer<'_> {
191 #[must_use]
192 pub const fn scopes(&self) -> &FunctionScopeState {
193 &self.scope
194 }
195}
196
197impl<'a> Analyzer<'a> {
198 pub fn new(
199 state: &'a mut ProgramState,
200 modules: &'a Modules,
201 core_symbol_table: SymbolTableRef,
202 source_map: &'a SourceMap,
203 module_path: &[String],
204 file_id: FileId,
205 ) -> Self {
206 let shared = SharedState {
207 state,
208 lookup_table: SymbolTable::new(&[]),
209 definition_table: SymbolTable::new(module_path),
210 modules,
211 core_symbol_table,
212 source_map,
213 file_id,
214 type_variables: SemanticContext::default(),
215 };
216 Self {
217 scope: FunctionScopeState::new(),
218 global: FunctionScopeState::new(),
219 shared,
220 module_path: module_path.to_vec(),
221 function_variables: Vec::new(),
222 }
223 }
224
225 fn start_function(&mut self) {
226 self.global.block_scope_stack = take(&mut self.scope.block_scope_stack);
227 self.scope = FunctionScopeState::new();
228 self.function_variables.clear();
229 }
230
231 fn stop_function(&mut self) {
232 self.scope.block_scope_stack = take(&mut self.global.block_scope_stack);
233 self.function_variables.clear();
234 }
235
236 fn analyze_if_expression(
237 &mut self,
238 condition: &swamp_ast::Expression,
239 true_expression: &swamp_ast::Expression,
240 maybe_false_expression: Option<&swamp_ast::Expression>,
241 context: &TypeContext,
242 ) -> Result<Expression, Error> {
243 let resolved_condition = self.analyze_bool_argument_expression(condition)?;
244
245 let branch_context = context;
246
247 let true_expr = self.analyze_expression(true_expression, branch_context)?;
248 let resolved_true = Box::new(true_expr);
249
250 let mut detected = context.expected_type.cloned();
251 if detected.is_none() && !matches!(resolved_true.ty, Type::Never) {
252 detected = Some(resolved_true.ty.clone());
253 }
254
255 let else_statements = if let Some(false_expression) = maybe_false_expression {
257 let else_context = branch_context.with_expected_type(detected.as_ref());
258 let else_expr = self.analyze_expression(false_expression, &else_context)?;
259 if detected.is_none() && !matches!(else_expr.ty, Type::Never) {
260 detected = Some(else_expr.ty.clone());
261 }
262
263 Some(Box::new(else_expr))
264 } else {
265 None
266 };
267
268 Ok(self.create_expr(
269 ExpressionKind::If(resolved_condition, resolved_true, else_statements),
270 detected.unwrap(),
271 &condition.node,
272 ))
273 }
274
275 fn get_text(&self, ast_node: &swamp_ast::Node) -> &str {
276 let span = Span {
277 file_id: self.shared.file_id,
278 offset: ast_node.span.offset,
279 length: ast_node.span.length,
280 };
281 self.shared.source_map.get_span_source(
282 self.shared.file_id,
283 span.offset as usize,
284 span.length as usize,
285 )
286 }
287
288 fn get_text_resolved(&self, resolved_node: &Node) -> &str {
289 let span = Span {
290 file_id: self.shared.file_id,
291 offset: resolved_node.span.offset,
292 length: resolved_node.span.length,
293 };
294 self.shared.source_map.get_span_source(
295 self.shared.file_id,
296 span.offset as usize,
297 span.length as usize,
298 )
299 }
300
301 fn get_path(&self, ident: &swamp_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
302 let path = ident
303 .module_path
304 .as_ref()
305 .map_or_else(Vec::new, |found_path| {
306 let mut v = Vec::new();
307 for p in &found_path.0 {
308 v.push(self.get_text(p).to_string());
309 }
310 v
311 });
312 (path, self.get_text(&ident.name.0).to_string())
313 }
314
315 fn analyze_return_type(&mut self, function: &swamp_ast::Function) -> Result<Type, Error> {
316 let ast_return_type = match function {
317 swamp_ast::Function::Internal(x) => &x.declaration.return_type,
318 swamp_ast::Function::External(x) => &x.return_type,
319 };
320
321 let resolved_return_type = match ast_return_type {
322 None => Type::Unit,
323 Some(x) => self.analyze_type(x)?,
324 };
325
326 Ok(resolved_return_type)
327 }
328
329 fn analyze_function_body_expression(
330 &mut self,
331 expression: &swamp_ast::Expression,
332 return_type: &Type,
333 ) -> Result<Expression, Error> {
334 let context = TypeContext::new_function(return_type);
335 let resolved_statement = self.analyze_expression(expression, &context)?;
336
337 Ok(resolved_statement)
338 }
339
340 fn analyze_maybe_type(&mut self, maybe_type: Option<&swamp_ast::Type>) -> Result<Type, Error> {
341 let found_type = match maybe_type {
342 None => Type::Unit,
343 Some(ast_type) => self.analyze_type(ast_type)?,
344 };
345 Ok(found_type)
346 }
347
348 fn analyze_for_pattern(
349 &mut self,
350 pattern: &swamp_ast::ForPattern,
351 key_type: Option<&Type>,
352 value_type: &Type,
353 ) -> Result<ForPattern, Error> {
354 match pattern {
355 swamp_ast::ForPattern::Single(var) => {
356 let variable_ref = self.create_local_variable(
357 &var.identifier,
358 Option::from(&var.is_mut),
359 value_type,
360 )?;
361 Ok(ForPattern::Single(variable_ref))
362 }
363 swamp_ast::ForPattern::Pair(first, second) => {
364 let found_key = key_type.unwrap();
365 let first_var_ref = self.create_local_variable(
366 &first.identifier,
367 Option::from(&first.is_mut),
368 found_key,
369 )?;
370 let second_var_ref = self.create_local_variable(
371 &second.identifier,
372 Option::from(&second.is_mut),
373 value_type,
374 )?;
375 Ok(ForPattern::Pair(first_var_ref, second_var_ref))
376 }
377 }
378 }
379
380 fn analyze_parameters(
381 &mut self,
382 parameters: &Vec<swamp_ast::Parameter>,
383 ) -> Result<Vec<TypeForParameter>, Error> {
384 let mut resolved_parameters = Vec::new();
385 for parameter in parameters {
386 let param_type = self.analyze_type(¶meter.param_type)?;
387 resolved_parameters.push(TypeForParameter {
388 name: self.get_text(¶meter.variable.name).to_string(),
389 resolved_type: param_type,
390 is_mutable: parameter.variable.is_mutable.is_some(),
391 node: Some(ParameterNode {
392 is_mutable: self.to_node_option(Option::from(¶meter.variable.is_mutable)),
393 name: self.to_node(¶meter.variable.name),
394 }),
395 });
396 }
397 Ok(resolved_parameters)
398 }
399
400 pub fn analyze_start_chain_expression_get_mutability(
403 &mut self,
404 ast_expression: &swamp_ast::Expression,
405 expected_type: Option<&Type>,
406 ) -> Result<(Expression, bool), Error> {
407 let any_parameter_context = TypeContext::new_unsure_argument(expected_type);
408 let resolved = self.analyze_expression(ast_expression, &any_parameter_context)?;
409 let mutability = match resolved.kind {
410 ExpressionKind::VariableAccess(ref resolved_variable) => resolved_variable.is_mutable(),
411 _ => false,
412 };
413
414 Ok((resolved, mutability))
415 }
416
417 pub fn debug_expression(&self, expr: &swamp_ast::Expression) {
418 let (line, _col) = self
419 .shared
420 .source_map
421 .get_span_location_utf8(self.shared.file_id, expr.node.span.offset as usize);
422 let _source_line = self
423 .shared
424 .source_map
425 .get_source_line(self.shared.file_id, line);
426 }
427
428 pub fn analyze_main_expression(
431 &mut self,
432 ast_expression: &swamp_ast::Expression,
433 ) -> Result<InternalMainExpression, Error> {
434 self.start_function();
435
436 let context = TypeContext::new_anything_argument();
437 let analyzed_expr = self.analyze_expression(ast_expression, &context)?;
438 let main_expr = InternalMainExpression {
439 expression: analyzed_expr,
440 function_scope_state: self.function_variables.clone(),
441 program_unique_id: self.shared.state.allocate_internal_function_id(),
442 };
443
444 self.stop_function();
445
446 Ok(main_expr)
447 }
448
449 fn analyze_maybe_ref_expression(
450 &mut self,
451 ast_expr: &swamp_ast::Expression,
452 ) -> Result<MaybeBorrowMutRefExpression, Error> {
453 if let swamp_ast::ExpressionKind::UnaryOp(found_unary, ast_inner_expression) =
454 &ast_expr.kind
455 {
456 if let swamp_ast::UnaryOperator::BorrowMutRef(node) = found_unary {
457 let resolved_node = self.to_node(node);
459 return Ok(MaybeBorrowMutRefExpression {
460 ast_expression: *ast_inner_expression.clone(),
461 has_borrow_mutable_reference: Some(resolved_node),
462 });
463 }
464 }
465
466 Ok(MaybeBorrowMutRefExpression {
467 ast_expression: ast_expr.clone(),
468 has_borrow_mutable_reference: None,
469 })
470 }
471
472 #[allow(clippy::too_many_lines)]
475 pub fn analyze_expression(
476 &mut self,
477 ast_expression: &swamp_ast::Expression,
478 context: &TypeContext,
479 ) -> Result<Expression, Error> {
480 let expr = self.analyze_expression_internal(ast_expression, context)?;
481
482 let encountered_type = expr.ty.clone();
483
484 if let Some(found_expected_type) = context.expected_type {
485 if found_expected_type.compatible_with(&encountered_type) {
486 return Ok(expr);
487 }
488
489 let result = self.types_did_not_match_try_late_coerce_expression(
490 expr,
491 found_expected_type,
492 &encountered_type,
493 &ast_expression.node,
494 )?;
495
496 return Ok(result);
497 }
498
499 Ok(expr)
500 }
501
502 #[allow(clippy::too_many_lines)]
505 pub fn analyze_expression_internal(
506 &mut self,
507 ast_expression: &swamp_ast::Expression,
508 context: &TypeContext,
509 ) -> Result<Expression, Error> {
510 let expression = match &ast_expression.kind {
511 swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
513 self.analyze_postfix_chain(postfix_chain)?
514 }
515
516 swamp_ast::ExpressionKind::VariableDefinition(
517 variable,
518 maybe_annotation,
519 source_expression,
520 ) => self.analyze_create_variable(
521 variable,
522 Option::from(maybe_annotation),
523 source_expression,
524 )?,
525
526 swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
527 self.analyze_variable_assignment(variable, source_expression)?
528 }
529
530 swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
531 self.analyze_destructuring(&ast_expression.node, variables, expression)?
532 }
533
534 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
535 self.analyze_identifier(qualified_identifier)?
536 }
537
538 swamp_ast::ExpressionKind::VariableReference(variable) => {
539 self.analyze_variable_reference(&variable.name)?
540 }
541
542 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
543 type_identifier,
544 member_name,
545 ) => self.analyze_static_member_access(type_identifier, member_name)?,
546
547 swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
548 self.analyze_constant_access(constant_identifier)?
549 }
550
551 swamp_ast::ExpressionKind::Assignment(location, source) => {
552 self.analyze_assignment(location, source)?
553 }
554
555 swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
556 self.analyze_assignment_compound(target, op, source)?
557 }
558
559 swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
561 let (resolved_op, result_type) =
562 self.analyze_binary_op(resolved_a, operator, resolved_b)?;
563
564 self.create_expr(
565 ExpressionKind::BinaryOp(resolved_op),
566 result_type,
567 &ast_expression.node,
568 )
569 }
570
571 swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
572 let (resolved_op, result_type) = self.analyze_unary_op(operator, expression)?;
573 self.create_expr(
574 ExpressionKind::UnaryOp(resolved_op),
575 result_type,
576 &ast_expression.node,
577 )
578 }
579
580 swamp_ast::ExpressionKind::Block(expressions) => {
581 let (block, resulting_type) =
582 self.analyze_block(&ast_expression.node, context, expressions)?;
583 self.create_expr(
584 ExpressionKind::Block(block),
585 resulting_type,
586 &ast_expression.node,
587 )
588 }
589
590 swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
591 self.analyze_with_expr(context, variable_bindings, expression)?
592 }
593
594 swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
595 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())?
596 }
597
598 swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
599 let kind = ExpressionKind::InterpolatedString(
600 self.analyze_interpolated_string(string_parts)?,
601 );
602
603 self.create_expr(kind, Type::String, &ast_expression.node)
604 }
605
606 swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
608 self.analyze_named_struct_literal(struct_identifier, fields, *has_rest)?
609 }
610
611 swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
612 .analyze_anonymous_struct_literal(
613 &ast_expression.node,
614 fields,
615 *rest_was_specified,
616 context,
617 )?,
618
619 swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
620 self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)?
621 }
622
623 swamp_ast::ExpressionKind::Literal(literal) => {
624 self.analyze_complex_literal_to_expression(&ast_expression.node, literal, context)?
625 }
626
627 swamp_ast::ExpressionKind::ForLoop(
628 pattern,
629 iterable_expression,
630 guard_expr,
631 statements,
632 ) => {
633 let _analyzed_guard = if let Some(found_guard) = guard_expr {
634 Some(self.analyze_bool_argument_expression(found_guard)?)
636 } else {
637 None
638 };
639
640 let resolved_iterator =
641 self.analyze_iterable(pattern.any_mut(), &iterable_expression.expression)?;
642
643 self.push_block_scope("for_loop");
644 let pattern = self.analyze_for_pattern(
645 pattern,
646 resolved_iterator.key_type.as_ref(),
647 &resolved_iterator.value_type,
648 )?;
649 let resolved_statements = self.analyze_expression(statements, context)?;
650 self.pop_block_scope("for_loop");
651 let resolved_type = resolved_statements.ty.clone();
652 self.create_expr(
653 ExpressionKind::ForLoop(
654 pattern,
655 resolved_iterator,
656 Box::from(resolved_statements),
657 ),
658 resolved_type,
659 &ast_expression.node,
660 )
661 }
662
663 swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
664 let condition = self.analyze_bool_argument_expression(expression)?;
665 let resolved_statements = self.analyze_expression(statements, context)?;
667 let resolved_type = resolved_statements.ty.clone();
668 self.create_expr(
671 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
672 resolved_type,
673 &ast_expression.node,
674 )
675 }
676
677 swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
678 self.analyze_if_expression(
679 expression,
680 true_expression,
681 maybe_false_expression.as_deref(),
682 context,
683 )?
684 }
685
686 swamp_ast::ExpressionKind::Match(expression, arms) => {
687 let (match_expr, return_type) = self.analyze_match(expression, context, arms)?;
688 self.create_expr(
689 ExpressionKind::Match(match_expr),
690 return_type,
691 &ast_expression.node,
692 )
693 }
694 swamp_ast::ExpressionKind::Guard(guard_expressions) => {
695 self.analyze_guard(&ast_expression.node, context, guard_expressions)?
696 }
697
698 swamp_ast::ExpressionKind::Lambda(variables, expression) => {
699 self.analyze_lambda(&ast_expression.node, variables, expression, context)?
700 }
701 };
702
703 Ok(expression)
706 }
707
708 fn get_struct_type(
709 &mut self,
710 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
711 ) -> Result<NamedStructType, Error> {
712 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier)?;
713 match maybe_struct_type {
714 Type::NamedStruct(struct_type) => Ok(struct_type),
715 _ => Err(self.create_err(
716 ErrorKind::UnknownStructTypeReference,
718 &qualified_type_identifier.name.0,
719 )),
720 }
721 }
722
723 pub(crate) fn analyze_named_type(
724 &mut self,
725 type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
726 ) -> Result<Type, Error> {
727 let (path, name) = self.get_path(type_name_to_find);
728
729 if path.is_empty() {
730 if let Some(found_type) = self.shared.type_variables.resolve_type_variable(&name) {
732 return Ok(found_type);
733 }
734 }
735
736 let symbol = {
737 let maybe_symbol_table = self.shared.get_symbol_table(&path);
738 let symbol_table = maybe_symbol_table.ok_or_else(|| {
739 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
740 })?;
741 symbol_table
742 .get_symbol(&name)
743 .ok_or_else(|| {
744 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
745 })?
746 .clone()
747 };
748
749 let mut analyzed_type_parameters = Vec::new();
750
751 for analyzed_type in &type_name_to_find.generic_params {
752 let ty = self.analyze_type(analyzed_type)?;
753
754 analyzed_type_parameters.push(ty);
755 }
756
757 let result_type = if analyzed_type_parameters.is_empty() {
758 match &symbol {
759 Symbol::Type(base_type) => base_type.clone(),
760 Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
761 _ => {
762 return Err(
763 self.create_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0)
764 );
765 }
766 }
767 } else {
768 self.analyze_generic_type(
769 &symbol,
770 &analyzed_type_parameters,
771 &type_name_to_find.name.0,
772 )?
773 };
774
775 Ok(result_type)
776 }
777
778 fn create_default_value_for_type(
779 &mut self,
780 node: &swamp_ast::Node,
781 field_type: &Type,
782 ) -> Result<Expression, Error> {
783 let kind = match field_type {
784 Type::Bool => ExpressionKind::Literal(Literal::BoolLiteral(false)),
785 Type::Int => ExpressionKind::Literal(Literal::IntLiteral(0)),
786 Type::Float => ExpressionKind::Literal(Literal::FloatLiteral(Fp::zero())),
787 Type::String => ExpressionKind::Literal(Literal::StringLiteral(String::new())),
788 Type::Tuple(tuple_type_ref) => {
789 let mut expressions = Vec::new();
790 for resolved_type in tuple_type_ref {
791 let expr = self.create_default_value_for_type(node, resolved_type)?;
792 expressions.push(expr);
793 }
794 ExpressionKind::Literal(Literal::TupleLiteral(tuple_type_ref.clone(), expressions))
795 }
796 Type::Optional(_optional_type) => ExpressionKind::Literal(Literal::NoneLiteral),
797
798 Type::NamedStruct(struct_ref) => {
799 self.create_default_static_call(node, &Type::NamedStruct(struct_ref.clone()))?
800 }
801 _ => {
802 return Err(
803 self.create_err(ErrorKind::NoDefaultImplemented(field_type.clone()), node)
804 );
805 }
806 };
807
808 let expr = self.create_expr(kind, field_type.clone(), node);
809 Ok(expr)
810 }
811
812 fn create_static_call(
813 &mut self,
814 function_name: &str,
815 arguments: &[MutRefOrImmutableExpression],
816 node: &swamp_ast::Node,
817 ty: &Type,
818 ) -> Result<ExpressionKind, Error> {
819 self.lookup_associated_function(ty, function_name)
820 .map_or_else(
821 || {
822 Err(self.create_err(
823 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
824 node,
825 ))
826 },
827 |function| {
828 let kind = match &*function {
829 Function::Internal(internal_function) => {
830 ExpressionKind::InternalFunctionAccess(internal_function.clone())
831 }
832 Function::External(external_function) => {
833 ExpressionKind::ExternalFunctionAccess(external_function.clone())
834 }
835 };
836
837 let base_expr =
838 self.create_expr(kind, Type::Function(function.signature().clone()), node);
839
840 let empty_call_postfix = Postfix {
841 node: self.to_node(node),
842 ty: *function.signature().return_type.clone(),
843 kind: PostfixKind::FunctionCall(arguments.to_vec()),
844 };
845
846 let kind =
847 ExpressionKind::PostfixChain(Box::new(base_expr), vec![empty_call_postfix]);
848
849 Ok(kind)
850 },
851 )
852 }
853
854 fn create_default_static_call(
855 &mut self,
856 node: &swamp_ast::Node,
857 ty: &Type,
858 ) -> Result<ExpressionKind, Error> {
859 self.create_static_call("default", &[], node, ty)
860 }
861
862 fn add_postfix(
863 &mut self,
864 vec: &mut Vec<Postfix>,
865 kind: PostfixKind,
866 ty: Type,
867 node: &swamp_ast::Node,
868 ) {
869 let resolved_node = self.to_node(node);
870 let postfix = Postfix {
871 node: resolved_node,
872 ty,
873 kind,
874 };
875
876 vec.push(postfix);
877 }
878
879 pub fn analyze_struct_field(
884 &mut self,
885 field_name: &swamp_ast::Node,
886 tv: &Type,
887 ) -> Result<(AnonymousStructType, usize, Type), Error> {
888 let field_name_str = self.get_text(field_name).to_string();
889
890 let anon_struct_ref = match &tv {
891 Type::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
892 Type::AnonymousStruct(anon_struct) => anon_struct.clone(),
893 _ => return Err(self.create_err(ErrorKind::UnknownStructField, field_name)),
894 };
895
896 if let Some(found_field) = anon_struct_ref
897 .field_name_sorted_fields
898 .get(&field_name_str)
899 {
900 let index = anon_struct_ref
901 .field_name_sorted_fields
902 .get_index(&field_name_str)
903 .expect("checked earlier");
904
905 return Ok((
906 anon_struct_ref.clone(),
907 index,
908 found_field.field_type.clone(),
909 ));
910 }
911
912 Err(self.create_err(ErrorKind::UnknownStructField, field_name))
913 }
914
915 #[allow(clippy::too_many_lines)]
916 fn analyze_postfix_chain(
917 &mut self,
918 chain: &swamp_ast::PostfixChain,
919 ) -> Result<Expression, Error> {
920 let (start, is_mutable) =
921 self.analyze_start_chain_expression_get_mutability(&chain.base, None)?;
922
923 if let ExpressionKind::IntrinsicFunctionAccess(some_access) = &start.kind {
924 assert_eq!(chain.postfixes.len(), 1);
925 let call_postifx = &chain.postfixes[0];
926 if let swamp_ast::Postfix::FunctionCall(_member, _generic_arguments, arguments) =
927 &call_postifx
928 {
929 let resolved_arguments = self.analyze_and_verify_parameters(
930 &start.node,
931 &some_access.signature.parameters,
932 arguments,
933 )?;
934
935 return Ok(self.create_expr(
936 ExpressionKind::IntrinsicCallEx(
937 some_access.intrinsic.clone(),
938 resolved_arguments,
939 ),
940 *some_access.signature.return_type.clone(),
941 &chain.base.node,
942 ));
943 }
944 panic!("not sure here");
945 }
946
947 let mut tv = TypeWithMut {
948 resolved_type: start.ty.clone(),
949 is_mutable,
950 };
951
952 let mut uncertain = false;
953
954 let mut suffixes = Vec::new();
955
956 for item in &chain.postfixes {
957 match item {
958 swamp_ast::Postfix::FieldAccess(field_name) => {
959 let (struct_type_ref, index, return_type) =
960 self.analyze_struct_field(&field_name.clone(), &tv.resolved_type)?;
961 self.add_postfix(
962 &mut suffixes,
963 PostfixKind::StructField(struct_type_ref.clone(), index),
964 return_type.clone(),
965 field_name,
966 );
967
968 tv.resolved_type = return_type.clone();
969 }
971 swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
972 let member_name_str = self.get_text(member_name).to_string();
973
974 if let Some(_found_member) = self
975 .shared
976 .state
977 .instantiator
978 .associated_impls
979 .get_member_function(&tv.resolved_type, &member_name_str)
980 {
981 let return_type = self.analyze_postfix_member_call(
982 &tv.resolved_type,
983 tv.is_mutable,
984 member_name,
985 generic_arguments.clone(),
986 ast_arguments,
987 &mut suffixes,
988 )?;
989
990 tv.resolved_type = return_type.clone();
992 tv.is_mutable = false;
993 } else {
994 return Err(self.create_err(ErrorKind::UnknownMemberFunction, member_name));
995 }
996 }
997 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
998 if let Type::Function(signature) = &tv.resolved_type {
999 let resolved_node = self.to_node(node);
1000 let resolved_arguments = self.analyze_and_verify_parameters(
1001 &resolved_node,
1002 &signature.parameters,
1003 arguments,
1004 )?;
1005
1006 let call_kind = PostfixKind::FunctionCall(resolved_arguments);
1007
1008 self.add_postfix(
1009 &mut suffixes,
1010 call_kind,
1011 *signature.return_type.clone(),
1012 node,
1013 );
1014
1015 tv.resolved_type = *signature.return_type.clone();
1016 tv.is_mutable = false;
1017 } else {
1018 panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
1019 }
1020 }
1021
1022 swamp_ast::Postfix::Subscript(index_expr) => {
1023 let _collection_type = tv.resolved_type.clone();
1024
1025 let temp_lookup_context = TypeContext::new_anything_argument();
1026 let temp_analyzed_expr =
1027 self.analyze_expression(index_expr, &temp_lookup_context)?;
1028
1029 let mut subscript_function_name = "subscript";
1030
1031 if let Type::NamedStruct(named_struct) = temp_analyzed_expr.ty {
1032 if named_struct.assigned_name == "Range"
1033 && named_struct.module_path == vec!["core-0.0.0".to_string()]
1034 {
1035 subscript_function_name = "subscript_range";
1036 }
1037 };
1038
1039 if let Some(found) = self
1040 .shared
1041 .state
1042 .instantiator
1043 .associated_impls
1044 .get_member_function(&tv.resolved_type, subscript_function_name)
1045 .cloned()
1046 {
1047 let cloned = found.clone();
1048 let required_type = &found.signature().parameters[1].resolved_type;
1049 let subscript_lookup_context = TypeContext::new_argument(&required_type);
1050 let analyzed_expr =
1051 self.analyze_expression(index_expr, &subscript_lookup_context)?;
1052
1053 let return_type = *found.signature().return_type.clone();
1054
1055 let argument = MutRefOrImmutableExpression::Expression(analyzed_expr);
1056 self.add_postfix(
1057 &mut suffixes,
1058 PostfixKind::MemberCall(cloned, vec![argument]),
1059 return_type.clone(),
1060 &index_expr.node,
1061 );
1062 tv.resolved_type = return_type.clone();
1063 } else {
1064 return Err(
1065 self.create_err(ErrorKind::MissingSubscriptMember, &index_expr.node)
1066 );
1067 }
1068 }
1069
1070 swamp_ast::Postfix::NoneCoalescingOperator(default_expr) => {
1071 let unwrapped_type = if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1072 unwrapped_type
1073 } else if uncertain {
1074 &tv.resolved_type
1075 } else {
1076 return Err(
1077 self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node)
1078 );
1079 };
1080
1081 let unwrapped_type_context = TypeContext::new_argument(unwrapped_type);
1082 let resolved_default_expr =
1083 self.analyze_expression(default_expr, &unwrapped_type_context)?;
1084 self.add_postfix(
1085 &mut suffixes,
1086 PostfixKind::NoneCoalescingOperator(resolved_default_expr),
1087 unwrapped_type.clone(),
1088 &default_expr.node,
1089 );
1090 tv.resolved_type = unwrapped_type.clone();
1091 uncertain = false; }
1093
1094 swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1095 if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1096 uncertain = true;
1097 self.add_postfix(
1098 &mut suffixes,
1099 PostfixKind::OptionalChainingOperator,
1100 *unwrapped_type.clone(),
1101 option_node,
1102 );
1103 tv.resolved_type = *unwrapped_type.clone();
1104 } else {
1105 return Err(self.create_err(ErrorKind::ExpectedOptional, option_node));
1106 }
1107 }
1108 }
1109 }
1110
1111 if uncertain {
1112 if let Type::Optional(_) = tv.resolved_type {
1113 } else {
1114 tv.resolved_type = Type::Optional(Box::from(tv.resolved_type.clone()));
1115 }
1116 }
1117
1118 Ok(self.create_expr(
1119 ExpressionKind::PostfixChain(Box::new(start), suffixes),
1120 tv.resolved_type,
1121 &chain.base.node,
1122 ))
1123 }
1124
1125 fn analyze_bool_argument_expression(
1126 &mut self,
1127 expression: &swamp_ast::Expression,
1128 ) -> Result<BooleanExpression, Error> {
1129 let bool_context = TypeContext::new_argument(&Type::Bool);
1130 let resolved_expression = self.analyze_expression(expression, &bool_context)?;
1131 let expr_type = resolved_expression.ty.clone();
1132
1133 let bool_expression = match expr_type {
1134 Type::Bool => resolved_expression,
1135 Type::Optional(_) => self.create_expr(
1136 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1137 Type::Bool,
1138 &expression.node,
1139 ),
1140 _ => {
1141 return Err(self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node));
1142 }
1143 };
1144
1145 Ok(BooleanExpression {
1146 expression: Box::from(bool_expression),
1147 })
1148 }
1149
1150 fn analyze_iterable(
1151 &mut self,
1152 force_mut: Option<swamp_ast::Node>,
1153 expression: &swamp_ast::Expression,
1154 ) -> Result<Iterable, Error> {
1155 let any_context = TypeContext::new_anything_argument();
1156 let resolved_expression: MutRefOrImmutableExpression = if force_mut.is_some() {
1157 let resolved_node = self.to_node(&force_mut.unwrap());
1158 MutRefOrImmutableExpression::Location(self.analyze_to_location(
1159 &expression,
1160 &any_context,
1161 LocationSide::Rhs,
1162 )?)
1163 } else {
1164 self.analyze_mut_or_immutable_expression(expression, &any_context, LocationSide::Rhs)?
1165 };
1166
1167 let resolved_type = &resolved_expression.ty().clone();
1168 let (key_type, value_type): (Option<Type>, Type) = match resolved_type {
1169 Type::String => (Some(Type::Int), Type::String),
1170
1171 _ => {
1172 if let Some(found_iter_fn) = self
1173 .shared
1174 .state
1175 .instantiator
1176 .associated_impls
1177 .get_internal_member_function(resolved_type, "iter")
1178 {
1179 let ret_type = found_iter_fn.signature.signature.return_type.clone();
1180 match *ret_type {
1181 Type::Tuple(tuple_items) => {
1182 (Some(tuple_items[0].clone()), tuple_items[1].clone())
1183 }
1184 _ => {
1185 return Err(self.create_err(ErrorKind::NotAnIterator, &expression.node));
1186 }
1187 }
1188 } else {
1189 return Err(self.create_err(ErrorKind::NotAnIterator, &expression.node));
1190 }
1191 }
1192 };
1193
1194 Ok(Iterable {
1195 key_type,
1196 value_type,
1197 resolved_expression: Box::new(resolved_expression),
1198 })
1199 }
1200
1201 fn analyze_argument_expressions(
1202 &mut self,
1203 expected_type: Option<&Type>,
1204 ast_expressions: &[swamp_ast::Expression],
1205 ) -> Result<Vec<Expression>, Error> {
1206 let mut resolved_expressions = Vec::new();
1207 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type);
1208 for expression in ast_expressions {
1209 resolved_expressions
1210 .push(self.analyze_expression(expression, &argument_expressions_context)?);
1211 }
1212 Ok(resolved_expressions)
1213 }
1214
1215 fn analyze_block(
1216 &mut self,
1217 _node: &swamp_ast::Node,
1218 context: &TypeContext,
1219 ast_expressions: &[swamp_ast::Expression],
1220 ) -> Result<(Vec<Expression>, Type), Error> {
1221 if ast_expressions.is_empty() {
1222 return Ok((vec![], Type::Unit));
1223 }
1224
1225 self.push_block_scope("block");
1226
1227 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1228
1229 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1230 let stmt_context = context.with_expected_type(Some(&Type::Unit));
1231 let expr = self.analyze_expression(expression, &stmt_context)?;
1232
1233 if matches!(expr.ty, Type::Never) {
1234 resolved_expressions.push(expr);
1235 return Ok((resolved_expressions, Type::Never));
1236 }
1237
1238 resolved_expressions.push(expr);
1239 }
1240
1241 let last_expr =
1243 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context)?;
1244 let last_type = last_expr.ty.clone();
1245 resolved_expressions.push(last_expr);
1246
1247 self.pop_block_scope("block");
1248
1249 Ok((resolved_expressions, last_type))
1250 }
1251
1252 fn analyze_interpolated_string(
1253 &mut self,
1254 string_parts: &[swamp_ast::StringPart],
1255 ) -> Result<Vec<StringPart>, Error> {
1256 let mut resolved_parts = Vec::new();
1257 for part in string_parts {
1258 let resolved_string_part = match part {
1259 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1260 StringPart::Literal(self.to_node(string_node), processed_string.to_string())
1261 }
1262 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1263 let any_context = TypeContext::new_anything_argument();
1264 let expr = self.analyze_expression(expression, &any_context)?;
1265 let resolved_format_specifier =
1266 self.analyze_format_specifier(Option::from(format_specifier));
1267 StringPart::Interpolation(expr, resolved_format_specifier)
1268 }
1269 };
1270
1271 resolved_parts.push(resolved_string_part);
1272 }
1273
1274 Ok(resolved_parts)
1275 }
1276
1277 pub(crate) fn analyze_identifier(
1278 &self,
1279 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1280 ) -> Result<Expression, Error> {
1281 if qualified_func_name.module_path.is_none()
1284 && qualified_func_name.generic_params.is_empty()
1285 {
1286 if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1287 return Ok(self.create_expr(
1288 ExpressionKind::VariableAccess(found_variable.clone()),
1289 found_variable.resolved_type.clone(),
1290 &qualified_func_name.name,
1291 ));
1292 }
1293 }
1294
1295 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
1296 let function_name = self.get_text(&qualified_func_name.name);
1297
1298 if let Some(found_table) = self.shared.get_symbol_table(&path) {
1299 if let Some(found_func) = found_table.get_function(function_name) {
1300 let (kind, signature) = match found_func {
1301 FuncDef::Internal(internal_fn) => (
1302 ExpressionKind::InternalFunctionAccess(internal_fn.clone()),
1303 &internal_fn.signature.signature,
1304 ),
1305 FuncDef::External(external_fn) => (
1306 ExpressionKind::ExternalFunctionAccess(external_fn.clone()),
1307 &external_fn.signature,
1308 ),
1309 FuncDef::Intrinsic(intrinsic_fn) => (
1311 ExpressionKind::IntrinsicFunctionAccess(intrinsic_fn.clone()),
1312 &intrinsic_fn.signature,
1313 ),
1314 };
1315
1316 return Ok(self.create_expr(
1317 kind,
1318 Type::Function(signature.clone()),
1319 &qualified_func_name.name,
1320 ));
1321 }
1322 }
1323 Err(self.create_err(
1324 ErrorKind::UnknownIdentifier(function_name.to_string()),
1325 &qualified_func_name.name,
1326 ))
1327 }
1328
1329 fn analyze_variable_reference(&self, var_node: &swamp_ast::Node) -> Result<Expression, Error> {
1331 if let Some(found_variable) = self.try_find_variable(var_node) {
1332 return Ok(self.create_expr(
1333 ExpressionKind::VariableAccess(found_variable.clone()),
1334 found_variable.resolved_type.clone(),
1335 var_node,
1336 ));
1337 }
1338 let text = self.get_text(var_node);
1339 Err(self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node))
1340 }
1341
1342 fn analyze_slice_type_helper(
1343 &mut self,
1344 node: &swamp_ast::Node,
1345 items: &[swamp_ast::Expression],
1346 context: &TypeContext,
1347 ) -> Result<(Type, Vec<Expression>), Error> {
1348 let maybe_expected_element_type = if let Some(expected_type) = context.expected_type {
1349 if let Type::Slice(inner_type) = expected_type {
1350 Some(*inner_type.clone())
1351 } else {
1352 if let Type::NamedStruct(named) = expected_type {
1353 Some(named.instantiated_type_parameters[0].clone())
1354 } else {
1355 return Err(self.create_err(ErrorKind::ExpectedSlice, &node));
1356 }
1357 }
1358 } else {
1359 None
1360 };
1361
1362 if items.is_empty() {
1363 context.expected_type.map_or_else(
1364 || Ok((Type::Unit, vec![])),
1365 |expected_type| {
1366 if let Type::Slice(_inner_type) = expected_type {
1367 Ok((expected_type.clone(), vec![]))
1368 } else if let Type::NamedStruct(named) = expected_type {
1369 Ok((named.instantiated_type_parameters[0].clone(), vec![]))
1370 } else {
1371 Err(self.create_err(ErrorKind::ExpectedSlice, node))
1372 }
1373 },
1374 )
1375 } else {
1376 let maybe_context =
1377 TypeContext::new_unsure_argument(maybe_expected_element_type.as_ref());
1378 let first = self.analyze_expression(&items[0], &maybe_context)?;
1379 let required_type = first.ty.clone();
1380 let required_context = TypeContext::new_argument(&required_type);
1381 let mut resolved_items = Vec::new();
1382 for item in items {
1383 let resolved_expr = self.analyze_expression(item, &required_context)?;
1384 resolved_items.push(resolved_expr);
1385 }
1386 Ok((first.ty, resolved_items))
1387 }
1388 }
1389
1390 fn push_block_scope(&mut self, _debug_str: &str) {
1391 self.scope.block_scope_stack.push(BlockScope {
1392 mode: BlockScopeMode::Open,
1393 variables: SeqMap::default(),
1394 });
1395 }
1396
1397 fn pop_block_scope(&mut self, _debug_str: &str) {
1398 self.scope.block_scope_stack.pop();
1399 }
1400
1401 fn push_closed_block_scope(&mut self) {
1402 self.scope.block_scope_stack.push(BlockScope {
1403 mode: BlockScopeMode::Closed,
1404 variables: SeqMap::default(),
1405 });
1406 }
1407
1408 fn pop_closed_block_scope(&mut self) {
1409 self.scope.block_scope_stack.pop();
1410 }
1411
1412 fn analyze_enum_variant_ref(
1413 &self,
1414 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1415 variant_name: &swamp_ast::LocalTypeIdentifier,
1416 ) -> Result<EnumVariantType, Error> {
1417 let variant_name_string = self.get_text(&variant_name.0).to_string();
1418 self.get_enum_variant_type(qualified_type_identifier, &variant_name_string)
1419 }
1420
1421 fn analyze_match(
1422 &mut self,
1423 scrutinee: &swamp_ast::Expression,
1424 default_context: &TypeContext,
1425 arms: &Vec<swamp_ast::MatchArm>,
1426 ) -> Result<(Match, Type), Error> {
1427 let mut known_type = default_context.expected_type.cloned();
1428 let own_context = default_context.clone();
1429 let scrutinee_context = TypeContext::new_anything_argument();
1431 let resolved_scrutinee = self.analyze_mut_or_immutable_expression(
1432 scrutinee,
1433 &scrutinee_context,
1434 LocationSide::Rhs,
1435 )?;
1436 let scrutinee_type = resolved_scrutinee.ty().clone();
1437
1438 if arms.is_empty() {
1440 return Err(self.create_err(ErrorKind::EmptyMatch, &scrutinee.node));
1441 }
1442
1443 let mut resolved_arms = Vec::with_capacity(arms.len());
1444
1445 for arm in arms {
1446 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1447 arm,
1448 &resolved_scrutinee,
1449 &own_context.with_expected_type(known_type.as_ref()),
1450 &scrutinee_type,
1451 )?;
1452
1453 if known_type.is_none() && !matches!(resolved_arm.expression.ty, Type::Never) {
1454 known_type = Some(resolved_arm.expression.ty.clone());
1455 }
1456 resolved_arms.push(resolved_arm);
1457 }
1458
1459 known_type.map_or_else(
1460 || Err(self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node)),
1461 |encountered_type| {
1462 if matches!(encountered_type, Type::Never) {
1463 Err(self.create_err(
1464 ErrorKind::IncompatibleTypes {
1465 expected: Type::Never,
1466 found: encountered_type,
1467 },
1468 &scrutinee.node,
1469 ))
1470 } else {
1471 Ok((
1472 Match {
1473 expression: Box::new(resolved_scrutinee),
1474 arms: resolved_arms,
1475 },
1476 encountered_type,
1477 ))
1478 }
1479 },
1480 )
1481 }
1482
1483 fn analyze_arm(
1484 &mut self,
1485 arm: &swamp_ast::MatchArm,
1486 _expression: &MutRefOrImmutableExpression,
1487 type_context: &TypeContext,
1488 expected_condition_type: &Type,
1489 ) -> Result<(MatchArm, bool), Error> {
1490 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1491 self.analyze_pattern(&arm.pattern, expected_condition_type)?;
1492
1493 let resolved_expression = self.analyze_expression(&arm.expression, type_context)?;
1494 if scope_was_pushed {
1495 self.pop_block_scope("analyze_arm");
1496 }
1497
1498 let resolved_type = resolved_expression.ty.clone();
1499
1500 Ok((
1501 MatchArm {
1502 pattern: resolved_pattern,
1503 expression: Box::from(resolved_expression),
1504 expression_type: resolved_type,
1505 },
1506 anyone_wants_mutable,
1507 ))
1508 }
1509
1510 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
1511 let text = text.replace('_', "");
1512 text.strip_prefix("0x").map_or_else(
1513 || {
1514 text.strip_prefix("-0x").map_or_else(
1515 || text.parse::<i32>(),
1516 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
1517 )
1518 },
1519 |rest| i32::from_str_radix(rest, 16),
1520 )
1521 }
1522
1523 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
1524 text.parse::<f32>()
1525 }
1526
1527 fn analyze_pattern_literal(
1528 &mut self,
1529 node: &swamp_ast::Node,
1530 ast_literal: &swamp_ast::LiteralKind,
1531 expected_condition_type: &Type,
1532 ) -> Result<NormalPattern, Error> {
1533 let required_condition_type_context = TypeContext::new_argument(expected_condition_type);
1534 let (literal, ty) =
1535 self.analyze_literal(node, ast_literal, &required_condition_type_context)?;
1536
1537 if !ty.compatible_with(expected_condition_type) {
1538 return Err(self.create_err(
1539 ErrorKind::IncompatibleTypes {
1540 expected: expected_condition_type.clone(),
1541 found: ty,
1542 },
1543 node,
1544 ));
1545 }
1546
1547 Ok(NormalPattern::Literal(literal))
1548 }
1549
1550 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
1551 Node {
1552 span: Span {
1553 file_id: self.shared.file_id,
1554 offset: node.span.offset,
1555 length: node.span.length,
1556 },
1557 }
1558 }
1559
1560 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
1561 module_path.as_ref().map_or_else(Vec::new, |found| {
1562 let mut strings = Vec::new();
1563 for path_item in &found.0 {
1564 strings.push(self.get_text(path_item).to_string());
1565 }
1566 strings
1567 })
1568 }
1569
1570 fn get_enum_variant_type(
1571 &self,
1572 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1573 variant_name: &str,
1574 ) -> Result<EnumVariantType, Error> {
1575 let (symbol_table, enum_name) =
1576 self.get_symbol_table_and_name(qualified_type_identifier)?;
1577 symbol_table
1578 .get_enum_variant_type(&enum_name, variant_name)
1579 .ok_or_else(|| {
1580 self.create_err(
1581 ErrorKind::UnknownEnumVariantType,
1582 &qualified_type_identifier.name.0,
1583 )
1584 })
1585 }
1586
1587 pub(crate) fn get_symbol_table_and_name(
1588 &self,
1589 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1590 ) -> Result<(&SymbolTable, String), Error> {
1591 let path = self.get_module_path(type_identifier.module_path.as_ref());
1592 let name = self.get_text(&type_identifier.name.0).to_string();
1593
1594 let maybe_symbol_table = self.shared.get_symbol_table(&path);
1595 maybe_symbol_table.map_or_else(
1596 || Err(self.create_err(ErrorKind::UnknownModule, &type_identifier.name.0)),
1597 |symbol_table| Ok((symbol_table, name)),
1598 )
1599 }
1600
1601 const fn analyze_compound_operator(
1602 &self,
1603 ast_operator: &swamp_ast::CompoundOperator,
1604 ) -> CompoundOperator {
1605 let resolved_node = self.to_node(&ast_operator.node);
1606 let resolved_kind = match ast_operator.kind {
1607 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
1608 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
1609 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
1610 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
1611 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
1612 };
1613
1614 CompoundOperator {
1615 node: resolved_node,
1616 kind: resolved_kind,
1617 }
1618 }
1619
1620 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
1621 match maybe_node {
1622 None => None,
1623 Some(node) => Some(self.to_node(node)),
1624 }
1625 }
1626
1627 const fn analyze_format_specifier(
1628 &self,
1629 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
1630 ) -> Option<FormatSpecifier> {
1631 let f = match ast_format_specifier {
1632 None => return None,
1633 Some(ast_format) => match ast_format {
1634 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
1635 node: self.to_node(node),
1636 kind: FormatSpecifierKind::LowerHex,
1637 },
1638 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
1639 node: self.to_node(node),
1640 kind: FormatSpecifierKind::UpperHex,
1641 },
1642 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
1643 node: self.to_node(node),
1644 kind: FormatSpecifierKind::Binary,
1645 },
1646 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
1647 node: self.to_node(node),
1648 kind: FormatSpecifierKind::Float,
1649 },
1650 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
1651 let (precision_type, precision_node) = match x {
1652 swamp_ast::PrecisionType::Float(node) => {
1653 (PrecisionType::Float, self.to_node(node))
1654 }
1655 swamp_ast::PrecisionType::String(node) => {
1656 (PrecisionType::String, self.to_node(node))
1657 }
1658 };
1659 FormatSpecifier {
1660 node: self.to_node(node),
1661 kind: FormatSpecifierKind::Precision(
1662 *value,
1663 precision_node,
1664 precision_type,
1665 ),
1666 }
1667 }
1668 },
1669 };
1670
1671 Some(f)
1672 }
1673
1674 fn analyze_with_expr(
1675 &mut self,
1676 context: &TypeContext,
1677 variables: &[swamp_ast::VariableBinding],
1678 expression: &swamp_ast::Expression,
1679 ) -> Result<Expression, Error> {
1680 let mut variable_expressions = Vec::new();
1681
1682 for variable in variables {
1683 let any_context = TypeContext::new_anything_argument();
1684
1685 let must_have_expression = if let Some(x) = &variable.expression {
1690 x
1691 } else {
1692 &swamp_ast::Expression {
1693 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
1694 node: variable.variable.name.clone(),
1695 }
1696
1697 };
1699
1700 let var = self.analyze_mut_or_immutable_expression(
1701 &must_have_expression,
1702 &any_context,
1703 LocationSide::Rhs,
1704 )?;
1705
1706 variable_expressions.push(var);
1707 }
1708
1709 self.push_closed_block_scope();
1710 let mut expressions = Vec::new();
1711 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
1712 let initialize_variable_expression = self.create_variable_binding_for_with(
1713 &variable_binding.variable,
1714 resolved_expression,
1715 )?;
1716 expressions.push(initialize_variable_expression);
1717 }
1718
1719 let resolved_expression = self.analyze_expression(expression, context)?;
1720 let block_type = resolved_expression.ty.clone();
1721 expressions.push(resolved_expression);
1722
1723 let block_expression_kind = ExpressionKind::Block(expressions);
1724 self.pop_closed_block_scope();
1725
1726 let block_expr = self.create_expr(block_expression_kind, block_type, &expression.node);
1727 Ok(block_expr)
1728 }
1729
1730 fn analyze_when_expr(
1731 &mut self,
1732 context: &TypeContext,
1733 variables: &[swamp_ast::VariableBinding],
1734 true_expr: &swamp_ast::Expression,
1735 else_expr: Option<&swamp_ast::Expression>,
1736 ) -> Result<Expression, Error> {
1737 self.push_block_scope("when");
1739 let mut bindings = Vec::new();
1740 for variable_binding in variables {
1741 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
1742 let any_context = TypeContext::new_anything_argument();
1743 self.analyze_mut_or_immutable_expression(
1744 found_expr,
1745 &any_context,
1746 LocationSide::Rhs,
1747 )?
1748 } else {
1749 let same_var = self.find_variable(&variable_binding.variable)?;
1750
1751 let argument_expression = if same_var.is_mutable() {
1752 let loc = SingleLocationExpression {
1753 kind: MutableReferenceKind::MutVariableRef,
1754 node: self.to_node(&variable_binding.variable.name),
1755 ty: Type::MutableReference(Box::from(same_var.resolved_type.clone())),
1756 starting_variable: same_var,
1757 access_chain: vec![],
1758 };
1759 MutRefOrImmutableExpression::Location(loc)
1760 } else {
1761 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
1762 let generated_expression = self.create_expr(
1763 generated_expr_kind,
1764 same_var.resolved_type.clone(),
1765 &variable_binding.variable.name,
1766 );
1767 MutRefOrImmutableExpression::Expression(generated_expression)
1768 };
1769
1770 argument_expression
1771 };
1772
1773 let ty = mut_expr.ty();
1774
1775 if let Type::Optional(found_ty) = ty {
1776 let variable_ref = self.create_variable(&variable_binding.variable, &found_ty)?;
1777
1778 let binding = WhenBinding {
1779 variable: variable_ref,
1780 expr: mut_expr,
1781 };
1782 bindings.push(binding);
1783 } else {
1784 return Err(self.create_err(ErrorKind::ExpectedOptional, &true_expr.node));
1785 }
1786 }
1787
1788 let resolved_true = self.analyze_expression(true_expr, context)?;
1789 let block_type = resolved_true.ty.clone();
1790
1791 self.pop_block_scope("when");
1792
1793 let maybe_resolved_else = if let Some(found_else) = else_expr {
1794 let block_type_for_true_context = context.we_know_expected_type(&block_type);
1795 Some(Box::new(self.analyze_expression(
1796 found_else,
1797 &block_type_for_true_context,
1798 )?))
1799 } else {
1800 None
1801 };
1802
1803 let when_kind =
1804 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
1805
1806 let block_expr = self.create_expr(when_kind, block_type, &true_expr.node);
1807 Ok(block_expr)
1808 }
1809
1810 fn analyze_guard(
1811 &mut self,
1812 node: &swamp_ast::Node,
1813 context: &TypeContext,
1814 guard_expressions: &Vec<swamp_ast::GuardExpr>,
1815 ) -> Result<Expression, Error> {
1816 let mut guards = Vec::new();
1817 let mut found_wildcard = None;
1818 let mut detected_type = context.expected_type.cloned();
1819
1820 for guard in guard_expressions {
1821 let resolved_condition = match &guard.clause {
1822 swamp_ast::GuardClause::Wildcard(x) => {
1823 if found_wildcard.is_some() {
1824 return Err(
1825 self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node)
1826 );
1827 }
1828 found_wildcard = Some(x);
1829 None
1830 }
1831 swamp_ast::GuardClause::Expression(clause_expr) => {
1832 if found_wildcard.is_some() {
1833 return Err(self.create_err(ErrorKind::WildcardMustBeLastInGuard, node));
1834 }
1835 Some(self.analyze_bool_argument_expression(clause_expr)?)
1836 }
1837 };
1838
1839 let resolved_result = self.analyze_expression(
1840 &guard.result,
1841 &context.with_expected_type(detected_type.as_ref()),
1842 )?;
1843 let ty = resolved_result.ty.clone();
1844 if detected_type.is_none() && !matches!(ty, Type::Never) {
1845 detected_type = Some(ty.clone());
1846 }
1847
1848 guards.push(Guard {
1849 condition: resolved_condition,
1850 result: resolved_result,
1851 });
1852 }
1853
1854 if found_wildcard.is_none() {
1855 return Err(self.create_err(ErrorKind::GuardMustHaveWildcard, node));
1856 }
1857
1858 let kind = ExpressionKind::Guard(guards);
1859
1860 detected_type.map_or_else(
1861 || Err(self.create_err(ErrorKind::GuardHasNoType, node)),
1862 |found_expecting_type| {
1863 let expr = self.create_expr(kind, found_expecting_type, node);
1864 Ok(expr)
1865 },
1866 )
1867 }
1868
1869 fn analyze_lambda(
1870 &mut self,
1871 node: &swamp_ast::Node,
1872 variables: &[swamp_ast::Variable],
1873 ast_expr: &swamp_ast::Expression,
1874 context: &TypeContext,
1875 ) -> Result<Expression, Error> {
1876 let Type::Function(signature) = &context.expected_type.unwrap() else {
1877 return Err(self.create_err(ErrorKind::ExpectedLambda, node));
1878 };
1879
1880 let return_block_type = TypeContext::new_argument(&signature.return_type);
1881
1882 self.push_block_scope("lambda");
1883
1884 let arity_required = signature.parameters.len();
1885 let variable_types_to_create = if variables.len() == arity_required {
1886 &signature.parameters
1887 } else if variables.len() + 1 == arity_required {
1888 &signature.parameters[1..].to_vec()
1889 } else {
1890 return Err(self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node));
1891 };
1892
1893 let mut resolved_variables = Vec::new();
1894 for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
1895 let variable_ref = self.create_local_variable(
1896 &variable.name,
1897 Some(node),
1898 &variable_type.resolved_type,
1899 )?;
1900 resolved_variables.push(variable_ref);
1901 }
1902
1903 let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type)?;
1904
1905 self.pop_block_scope("lambda");
1906
1907 Ok(self.create_expr(
1908 ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
1909 Type::Function(signature.clone()),
1910 node,
1911 ))
1912 }
1913
1914 pub fn analyze_variable_assignment(
1917 &mut self,
1918 variable: &swamp_ast::Variable,
1919 source_expression: &swamp_ast::Expression,
1920 ) -> Result<Expression, Error> {
1921 let maybe_found_variable = self.try_find_variable(&variable.name);
1922
1923 let required_type = maybe_found_variable
1924 .as_ref()
1925 .map(|found_variable| found_variable.resolved_type.clone());
1926
1927 let context = TypeContext::new_unsure_argument(required_type.as_ref());
1928
1929 let source_expr = self.analyze_expression(source_expression, &context)?;
1930 let ty = source_expr.ty.clone();
1931 if !ty.is_concrete() {
1932 return Err(self.create_err(ErrorKind::VariableTypeMustBeConcrete, &variable.name));
1933 }
1934
1935 let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
1936 if !found_var.is_mutable() {
1937 return Err(self.create_err(ErrorKind::VariableIsNotMutable, &variable.name));
1938 }
1939 if !found_var.resolved_type.assignable_type(&ty) {
1940 return Err(self.create_err(
1941 ErrorKind::IncompatibleTypes {
1942 expected: ty,
1943 found: found_var.resolved_type.clone(),
1944 },
1945 &variable.name,
1946 ));
1947 }
1948 ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
1949 } else {
1950 let new_var = self.create_variable(variable, &ty)?;
1951 ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
1952 };
1953
1954 Ok(self.create_expr(kind, Type::Unit, &variable.name))
1955 }
1956
1957 fn analyze_create_variable(
1958 &mut self,
1959 var: &swamp_ast::Variable,
1960 annotation_type: Option<&swamp_ast::Type>,
1961 source_expression: &swamp_ast::Expression,
1962 ) -> Result<Expression, Error> {
1963 let ty = if let Some(found_ast_type) = annotation_type {
1964 Some(self.analyze_type(found_ast_type)?)
1965 } else {
1966 None
1967 };
1968
1969 let unsure_arg_context = TypeContext::new_unsure_argument(ty.as_ref());
1970
1971 let resolved_source = self.analyze_expression(source_expression, &unsure_arg_context)?;
1972
1973 let var_ref = self.create_local_variable(
1974 &var.name,
1975 Option::from(&var.is_mutable),
1976 &resolved_source.ty,
1977 )?;
1978
1979 let resolved_type = resolved_source.ty.clone();
1980 assert_ne!(resolved_type, Type::Unit);
1981 let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
1982
1983 let resolved_expr = self.create_expr(kind, Type::Unit, &var.name);
1984
1985 Ok(resolved_expr)
1986 }
1987
1988 fn add_location_item(
1989 &mut self,
1990 vec: &mut Vec<LocationAccess>,
1991 kind: LocationAccessKind,
1992 ty: Type,
1993 ast_node: &swamp_ast::Node,
1994 ) {
1995 let resolved_node = self.to_node(ast_node);
1996 let postfix = LocationAccess {
1997 node: resolved_node,
1998 ty,
1999 kind,
2000 };
2001
2002 vec.push(postfix);
2003 }
2004
2005 fn extract_single_intrinsic_call(body: &Expression) -> Option<IntrinsicFunction> {
2006 match &body.kind {
2007 ExpressionKind::Block(expressions) => {
2008 let first_kind = &expressions[0].kind;
2009 if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, _args) = first_kind {
2010 return Some(intrinsic_fn.clone());
2011 }
2012 }
2013 _ => {}
2014 }
2015 None
2016 }
2017
2018 #[allow(clippy::too_many_lines)]
2019 fn analyze_chain_to_location(
2020 &mut self,
2021 chain: &swamp_ast::PostfixChain,
2022 context: &TypeContext,
2023 location_side: LocationSide,
2024 ) -> Result<SingleLocationExpression, Error> {
2025 let mut items = Vec::new();
2026
2027 let nothing_context = TypeContext::new(None);
2028
2029 let base_expr = self.analyze_expression(&chain.base, ¬hing_context)?;
2030 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
2031 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node));
2032 };
2033
2034 if !start_variable.is_mutable() {
2035 return Err(self.create_err(ErrorKind::VariableIsNotMutable, &chain.base.node));
2036 }
2037
2038 let mut ty = start_variable.resolved_type.clone();
2039 for (i, item) in chain.postfixes.iter().enumerate() {
2040 match &item {
2041 swamp_ast::Postfix::FieldAccess(field_name_node) => {
2042 let (struct_type_ref, index, return_type) =
2044 self.analyze_struct_field(field_name_node, &ty)?;
2045 self.add_location_item(
2046 &mut items,
2047 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2048 return_type.clone(),
2049 field_name_node,
2050 );
2051
2052 ty = return_type.clone();
2053 }
2054 swamp_ast::Postfix::Subscript(key_expression) => {
2055 let is_last_in_chain = i == chain.postfixes.len() - 1;
2056 let create_if_not_exists =
2057 is_last_in_chain && location_side == LocationSide::Lhs;
2058
2059 let subscript_member_function_name = if create_if_not_exists {
2060 "subscript_mut_create_if_needed"
2061 } else {
2062 "subscript_mut"
2063 };
2064
2065 if let Some(found) = self
2066 .shared
2067 .state
2068 .instantiator
2069 .associated_impls
2070 .get_internal_member_function(&ty, subscript_member_function_name)
2071 .cloned()
2072 {
2073 let intrinsic_to_call =
2074 Self::extract_single_intrinsic_call(&found.body).expect("must exist");
2075
2076 let create_if_not_exists_bool_expr = self.create_expr(
2077 ExpressionKind::Literal(Literal::BoolLiteral(create_if_not_exists)),
2078 Type::Bool,
2079 &chain.base.node,
2080 );
2081
2082 let required_type = &found.signature.signature.parameters[1].resolved_type;
2083 let subscript_lookup_context = TypeContext::new_argument(required_type);
2084 let analyzed_key_expression =
2085 self.analyze_expression(key_expression, &subscript_lookup_context)?;
2086 let return_type = *found.signature.signature.return_type.clone();
2087 ty = return_type.clone();
2088 self.add_location_item(
2090 &mut items,
2091 LocationAccessKind::IntrinsicCallMut(
2092 intrinsic_to_call,
2093 vec![analyzed_key_expression, create_if_not_exists_bool_expr],
2094 ),
2095 return_type,
2096 &key_expression.node,
2097 );
2098 } else {
2099 return Err(self
2100 .create_err(ErrorKind::MissingSubscriptMember, &key_expression.node));
2101 }
2102 }
2103
2104 swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
2105 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2106 }
2107
2108 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
2109 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2110 }
2111 swamp_ast::Postfix::OptionalChainingOperator(node) => {
2112 return Err(self.create_err(ErrorKind::UnwrapCanNotBePartOfChain, node));
2113 }
2114 swamp_ast::Postfix::NoneCoalescingOperator(expr) => {
2115 return Err(
2116 self.create_err(ErrorKind::NoneCoalesceCanNotBePartOfChain, &expr.node)
2117 );
2118 }
2119 }
2120 }
2121
2122 if let Some(found_expected_type) = context.expected_type {
2123 if !ty.compatible_with(found_expected_type) {
2124 return Err(self.create_err(
2125 ErrorKind::IncompatibleTypes {
2126 expected: found_expected_type.clone(),
2127 found: ty,
2128 },
2129 &chain.base.node,
2130 ));
2131 }
2132 }
2133
2134 let location = SingleLocationExpression {
2135 kind: MutableReferenceKind::MutVariableRef,
2136 node: self.to_node(&chain.base.node),
2137 ty,
2138 starting_variable: start_variable,
2139 access_chain: items,
2140 };
2141 Ok(location)
2142 }
2143
2144 fn analyze_to_location(
2145 &mut self,
2146 expr: &swamp_ast::Expression,
2147 context: &TypeContext,
2148 location_type: LocationSide,
2149 ) -> Result<SingleLocationExpression, Error> {
2150 match &expr.kind {
2151 swamp_ast::ExpressionKind::PostfixChain(chain) => {
2152 self.analyze_chain_to_location(chain, context, location_type)
2153 }
2154 swamp_ast::ExpressionKind::VariableReference(variable) => {
2155 let var = self.find_variable(variable)?;
2156 if var.is_mutable() {
2157 Ok(SingleLocationExpression {
2158 kind: MutableReferenceKind::MutVariableRef,
2159 node: self.to_node(&variable.name),
2160 ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2161 starting_variable: var,
2162 access_chain: vec![],
2163 })
2164 } else {
2165 Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2166 }
2167 }
2168 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
2169 let generated_var = swamp_ast::Variable {
2170 name: qualified_identifier.name.clone(),
2171 is_mutable: None,
2172 };
2173 let var = self.find_variable(&generated_var)?;
2174 if var.is_mutable() {
2175 Ok(SingleLocationExpression {
2176 kind: MutableReferenceKind::MutVariableRef,
2177 node: self.to_node(&generated_var.name),
2178 ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2179 starting_variable: var,
2180 access_chain: vec![],
2181 })
2182 } else {
2183 Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2184 }
2185 }
2186 _ => Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &expr.node)),
2187 }
2188 }
2189
2190 fn analyze_assignment_compound(
2191 &mut self,
2192 target_expression: &swamp_ast::Expression,
2193 ast_op: &swamp_ast::CompoundOperator,
2194 ast_source_expression: &swamp_ast::Expression,
2195 ) -> Result<Expression, Error> {
2196 let resolved_op = self.analyze_compound_operator(ast_op);
2197 let any_argument_context = TypeContext::new_anything_argument();
2198 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context)?;
2199 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty);
2200
2201 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
2202 target_expression,
2203 &source_expr_type_context,
2204 LocationSide::Rhs,
2205 )?);
2206
2207 let kind = ExpressionKind::CompoundAssignment(
2208 resolved_location,
2209 resolved_op.kind,
2210 Box::from(source_expr),
2211 );
2212
2213 let expr = self.create_expr(kind, Type::Unit, &target_expression.node);
2214
2215 Ok(expr)
2216 }
2217
2218 fn analyze_assignment(
2219 &mut self,
2220 target_location: &swamp_ast::Expression,
2221 ast_source_expression: &swamp_ast::Expression,
2222 ) -> Result<Expression, Error> {
2223 let any_argument_context = TypeContext::new_anything_argument();
2224 let resolved_location =
2225 self.analyze_to_location(target_location, &any_argument_context, LocationSide::Lhs)?;
2226
2227 let ty = resolved_location.ty.clone();
2228 assert!(ty.is_concrete());
2229
2230 let lhs_argument_context = TypeContext::new_argument(&ty);
2231 let source_expr = self.analyze_expression(ast_source_expression, &lhs_argument_context)?;
2232
2233 let mut_location = TargetAssignmentLocation(resolved_location);
2234
2235 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
2236
2237 let expr = self.create_expr(kind, Type::Unit, &target_location.node); Ok(expr)
2240 }
2241
2242 #[must_use]
2243 pub const fn create_expr(
2244 &self,
2245 kind: ExpressionKind,
2246 ty: Type,
2247 ast_node: &swamp_ast::Node,
2248 ) -> Expression {
2249 Expression {
2251 kind,
2252 ty,
2253 node: self.to_node(ast_node),
2254 }
2255 }
2256
2257 #[must_use]
2258 pub fn create_expr_resolved(
2259 &self,
2260 kind: ExpressionKind,
2261 ty: Type,
2262 ast_node: &Node,
2263 ) -> Expression {
2264 Expression {
2265 kind,
2266 ty,
2267 node: ast_node.clone(),
2268 }
2269 }
2270
2271 fn analyze_destructuring(
2272 &mut self,
2273 node: &swamp_ast::Node,
2274 target_ast_variables: &[swamp_ast::Variable],
2275 tuple_expression: &swamp_ast::Expression,
2276 ) -> Result<Expression, Error> {
2277 let any_context = TypeContext::new_anything_argument();
2278 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context)?;
2279 let tuple_expr_type = &tuple_resolved.ty;
2280
2281 let mut variable_refs = Vec::new();
2282 if let Type::Tuple(tuple) = tuple_expr_type.clone() {
2283 if target_ast_variables.len() > tuple.len() {
2284 return Err(self.create_err(ErrorKind::TooManyDestructureVariables, node));
2285 }
2286 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
2287 let variable_ref = self.create_local_variable(
2288 &ast_variable.name,
2289 ast_variable.is_mutable.as_ref(),
2290 &tuple_type,
2291 )?;
2292 variable_refs.push(variable_ref);
2293 }
2294 let expr_kind =
2295 ExpressionKind::TupleDestructuring(variable_refs, tuple, Box::from(tuple_resolved));
2296
2297 Ok(self.create_expr(expr_kind, Type::Unit, node))
2298 } else {
2299 Err(self.create_err(ErrorKind::CanNotDestructure, node))
2300 }
2301 }
2302
2303 fn analyze_postfix_member_call(
2304 &mut self,
2305 type_that_member_is_on: &Type,
2306 is_mutable: bool,
2307 member_name: &swamp_ast::Node,
2308 ast_maybe_generic_arguments: Option<Vec<swamp_ast::Type>>,
2309 arguments: &[swamp_ast::Expression],
2310 suffixes: &mut Vec<Postfix>,
2311 ) -> Result<Type, Error> {
2312 let field_name_str = self.get_text(member_name).to_string();
2313
2314 let resolved_node = self.to_node(member_name);
2315
2316 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
2317 let mut resolved_types = Vec::new();
2318 for ast_type in ast_generic_arguments {
2319 resolved_types.push(self.analyze_type(&ast_type)?);
2320 }
2321 resolved_types
2322 } else {
2323 vec![]
2324 };
2325
2326 let maybe_function = self
2327 .shared
2328 .state
2329 .instantiator
2330 .associated_impls
2331 .get_member_function(type_that_member_is_on, &field_name_str)
2332 .cloned();
2333
2334 let Some(found_function) = maybe_function else {
2335 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, member_name));
2336 };
2337
2338 let (maybe_generic, alternative_signature) = found_function.signatures();
2339
2340 let signature = if let Some(found_generic) = maybe_generic {
2341 let mut seq_map = SeqMap::new();
2342 if generic_arguments.len() != found_generic.generic_type_variables.len() {
2343 return Err(self
2344 .create_err_resolved(ErrorKind::WrongNumberOfArguments(0, 0), &resolved_node));
2345 }
2346 for (variable, generic_argument_type) in found_generic
2347 .generic_type_variables
2348 .iter()
2349 .zip(generic_arguments)
2350 {
2351 info!(?variable, ?generic_argument_type, "SETTING VAR");
2352 seq_map
2353 .insert(variable.0.to_string(), generic_argument_type.clone())
2354 .unwrap();
2355 }
2356 let scope = TypeVariableScope::new(seq_map);
2357 let instantiated_signature = self
2358 .shared
2359 .state
2360 .instantiator
2361 .instantiate_generic_signature(type_that_member_is_on, found_generic, &scope)?
2362 .clone();
2363
2364 &instantiated_signature.clone()
2365 } else {
2366 alternative_signature
2367 };
2368
2369 let self_type = &signature.parameters[0];
2370 if !self_type
2371 .resolved_type
2372 .compatible_with(type_that_member_is_on)
2373 || self_type.is_mutable && !is_mutable
2374 {
2375 return Err(self.create_err_resolved(ErrorKind::SelfNotCorrectType, &resolved_node));
2376 }
2377
2378 let resolved_arguments = self.analyze_and_verify_parameters(
2379 &resolved_node,
2380 &signature.parameters[1..],
2381 arguments,
2382 )?;
2383
2384 let kind = PostfixKind::MemberCall(found_function.clone(), resolved_arguments);
2385
2386 let postfix = Postfix {
2387 node: resolved_node.clone(),
2388 ty: *signature.return_type.clone(),
2389 kind,
2390 };
2391
2392 let last_type = postfix.ty.clone();
2393 suffixes.push(postfix);
2394
2395 Ok(last_type)
2396 }
2397
2398 fn types_did_not_match_try_late_coerce_expression(
2399 &self,
2400 expr: Expression,
2401 expected_type: &Type,
2402 encountered_type: &Type,
2403 node: &swamp_ast::Node,
2404 ) -> Result<Expression, Error> {
2405 if let Type::Optional(expected_inner_type) = expected_type {
2406 assert!(
2409 expected_inner_type
2410 .inner_optional_mut_or_immutable()
2411 .is_none()
2412 );
2413
2414 if encountered_type.inner_optional_mut_or_immutable().is_none() {
2416 if expected_inner_type.compatible_ignore_mutability_of(encountered_type) {
2418 let wrapped = self.create_expr(
2420 ExpressionKind::Option(Option::from(Box::new(expr))),
2421 expected_type.clone(),
2422 node,
2423 );
2424 return Ok(wrapped);
2425 }
2426 }
2427 } else if matches!(expected_type, &Type::Bool) {
2428 if encountered_type.inner_optional_mut_or_immutable().is_some() {
2430 let wrapped = self.create_expr(
2431 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
2432 Type::Bool,
2433 node,
2434 );
2435 return Ok(wrapped);
2436 }
2437 }
2438
2439 Err(self.create_err(
2440 ErrorKind::IncompatibleTypes {
2441 expected: expected_type.clone(),
2442 found: encountered_type.clone(),
2443 },
2444 node,
2445 ))
2446 }
2447
2448 #[allow(clippy::too_many_lines)]
2449 fn analyze_generic_type(
2450 &mut self,
2451 symbol: &Symbol,
2452 analyzed_type_parameters: &[Type],
2453 node: &swamp_ast::Node,
2454 ) -> Result<Type, Error> {
2455 let ty = match symbol {
2456 Symbol::Blueprint(blueprint) => {
2459 if all_types_are_concrete_or_unit(analyzed_type_parameters) {
2460 self.shared
2461 .state
2462 .instantiator
2463 .instantiate_blueprint_and_members(blueprint, analyzed_type_parameters)?
2464 } else {
2465 Type::Generic(blueprint.clone(), analyzed_type_parameters.to_vec())
2466 }
2467 }
2468 Symbol::TypeGenerator(type_gen) => match type_gen.kind {
2469 TypeGeneratorKind::Slice => {
2470 Type::Slice(Box::new(analyzed_type_parameters[0].clone()))
2472 }
2473 TypeGeneratorKind::SlicePair => {
2474 Type::SlicePair(
2477 Box::new(analyzed_type_parameters[0].clone()),
2478 Box::new(analyzed_type_parameters[1].clone()),
2479 )
2480 }
2481 },
2482 _ => return Err(self.create_err(ErrorKind::UnknownSymbol, node)),
2483 };
2484
2485 Ok(ty)
2486 }
2487}