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